这是编译期错误,因字面量42不可寻址,&只能作用于有固定内存位置的具名变量,而42是无地址的临时值。

cannot take the address of 42 是什么问题
这是编译期错误,不是运行时 panic。根本原因是 & 只能作用于「可寻址变量」——即有固定内存位置、生命周期明确的具名变量。
-
&42、&"hello"、&true都非法:字面量没有地址 -
&m["k"]非法:map value 是临时拷贝,不是变量;要改值直接写m["k"] = v -
&getValue()非法:除非函数返回的是一个变量本身(如返回局部变量地址是逃逸行为,但返回全局/堆变量地址合法),否则返回值不可寻址 -
&s[0]在切片上通常合法(s是变量,s[0]是其元素,可寻址),但&s[i]中i超界时编译不报错,运行时 panic
func f(p *int) 和 func f(* p int) 哪个对
只有 func f(p *int) 合法。* 必须紧贴类型,不能和参数名混在一起。
-
func f(*int)是合法签名(无名参数),但可读性差,不推荐 -
func f(* p int)直接编译失败:语法错误,Go 不接受*与参数名之间有空格或分离写法 -
var p *int中的*int是完整类型名,和[]string一样,是声明的一部分;而*p中的*是独立操作符,用于解引用 - 误写成
func f(p * int)(*和int间有空格)也会编译失败
*[3]int 和 []int 完全不兼容
看到 *[3]int 别当成“数组指针”就完事——它是 Go 中一种独立类型,语义严格:指向「长度固定为 3 的 int 数组」的指针,N 是类型一部分,不可省略、不可隐式转换。
-
arr := [3]int{1,2,3}; p := &arr→p类型是*[3]int,不是*[]int,也不能赋给*[5]int -
json.Unmarshal(data, &arr)合法;但json.Unmarshal(data, &slice)❌ 编译失败,因为slice是[]int,&slice是*[]int,类型不匹配 - 想把
*[3]int当切片用?得显式转:myFunc((*p)[:]),否则传不进接受[]int的函数 - 大定长数组(如
[1024]byte)才值得用*[N]T避免拷贝;小数组传值更轻量
nil 指针解引用为什么必 panic
Go 不做空指针防护,*p 在 p == nil 时直接崩溃。这不是缺陷,是设计选择:强制你显式检查,避免静默逻辑错误。
-
var p *int; *p = 5→ 编译通过,运行时 panic:invalid memory address or nil pointer dereference - 函数返回
*User(如findUser(id)),必须先if u != nil再用u.Name -
reflect.ValueOf(ptr).Elem()前,必须确认ptr是指针且非 nil:reflect.ValueOf(ptr).Kind() == reflect.Ptr && !reflect.ValueOf(ptr).IsNil() - 接口变量底层是 nil 指针时调方法也会 panic:
var s io.Reader = (*bytes.Buffer)(nil); s.Read(nil)→ crash
实际编码中最容易被忽略的,是「可寻址性」这个前提——它不取决于你写了什么,而取决于那个值是不是一个真正存在于内存某处、有名字、有生命周期的变量。很多 panic 和编译错误,追到底都是忘了这一点。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











