Go-指针的那些事

<<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) // 内存泄漏, 获取到了某个地址指向的数据. 如果改了, 可能会导致不可知的问题
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值