当前位置:网站首页>Go-指针的那些事

Go-指针的那些事

2022-08-09 09:27:00 草明

<<Go 语言核心 36 讲>> 郝林 总结的

不可寻址的值:

  1. 常量的值。
  2. 基本类型值的字面量。
  3. 算术操作的结果值。
  4. 对各种字面量的索引表达式和切片表达式的结果值。不过有一个例外,对切片字面量的索引结果值却是可寻址的。
  5. 对字符串变量的索引表达式和切片表达式的结果值。
  6. 对字典变量的索引表达式的结果值。
  7. 函数字面量和方法字面量,以及对它们的调用表达式的结果值。
  8. 结构体字面量的字段值,也就是对结构体字面量的选择表达式的结果值。
  9. 类型转换表达式的结果值。
  10. 类型断言表达式的结果值。
  11. 接收表达式的结果值。

规律:

  • 不可变的 - 寻址没有意义, 不能改
  • 临时结果 - 例外, 切片字面量的索引结果值.
  • 不安全的 - "不安全的"操作很可能会破坏程序的一致性,引发不可预知的错误,从而严重影响程序的功能和稳定性。

上代码, 自己品

package main

type Pet interface {
    
	Name() string
	Category() string
}

type Dog struct {
    
	name string
}

func (self Dog) SetName(name string) {
    
	self.name = name
}

func (self Dog) Name() string {
    
	return self.name
}

func (self Dog) Category() string {
    
	return "Dog"
}

func New(name string) Dog {
    
	return Dog{
    name}
}

func main() {
    
	// 不会报错. 不需要指针类型调用 SetName
	New("Max").SetName("Bear")
}
package main

type Pet interface {
    
	Name() string
	Category() string
}

type Dog struct {
    
	name string
}

func (self *Dog) SetName(name string) {
    
	self.name = name
}

func (self *Dog) Name() string {
    
	return self.name
}

func (self *Dog) Category() string {
    
	return "Dog"
}

func New(name string) Dog {
    
	return Dog{
    name}
}

func main() {
    
	dog := New("Max")
	dog.SetName("Bear") // 编译器会自动转换成 (&dog).SetName("Bear")


	// 会报错, 因为 New("Max") 是临时结果, 不可以寻址, 无法获取指针
	New("Max").SetName("Bear")
	// cannot call pointer method on New("Max")
	// cannot take the address of New("Max")
}
package main

import (
	"fmt"
)

func main() {
    
	map[string]int{
    "the": 0, "word": 0, "counter": 0}["word"]++

	map1 := map[string]int{
    "the": 0, "word": 0, "counter": 0}
	map1["word"]++
	fmt.Println(map1["word"]) // 1
}
package main

import (
	"fmt"
	"unsafe"
)

type Dog struct {
    
	name string
}

func (self *Dog) SetName(name string) {
    
	self.name = name
}

func (self *Dog) Name() string {
    
	return self.name
}

func (self *Dog) Category() string {
    
	return "Dog"
}

func main() {
    
	dog := Dog{
    }
	dog.SetName("Max")
	dogP := &dog
	dogPtr := uintptr(unsafe.Pointer(dogP))

	namePtr := dogPtr + unsafe.Offsetof(dogP.name)
	nameP := (*string)(unsafe.Pointer(namePtr))
	fmt.Println(*nameP) // Max

	namePtr = dogPtr + 64
	unknownP := (*[]byte)(unsafe.Pointer(namePtr))
	fmt.Println(*unknownP) // 内存泄漏, 获取到了某个地址指向的数据. 如果改了, 可能会导致不可知的问题
}
原网站

版权声明
本文为[草明]所创,转载请带上原文链接,感谢
https://blog.csdn.net/galoiszhou/article/details/122707046