本博文主要记录一些go学习中一些小坑。但是不会一个系统性的文章。、
1. import后面的最后一个元素是包名。这一说法是否正确。
答案:这是错的。import后面的最后一个元素应该是路径,就是目录,并非包名。
为此我专门写了一个包试一下。我将包的文件夹名字命名为tested
然后把包名定义为foo
。然后在main
进行调用。发现并不能根据路径名tested
调用,而只能使用foo
调用。
// GOPTAH/src/tested
package foo
import "fmt"
func Foo() {
fmt.Println("in tested file")
}
测试代码:
package main
import (
"tested"
)
func main() {
//tested.Foo() // 错误编译器会提醒
foo.Foo()
}
2. map一定要使用make分配内存后才能使用。
var list []int
list = append(list, 0)
var m map[string]int
m["one"] = 1 // 错误的,没有使用make
当然两者都可以用make
3. 对于常量赋值,绝对不能使用函数或者方法来初始化。
常量初始化的时候,其右值必须是一个常量表达式,而不应该是函数调用。比如1<<3
,18^9
这种就是常量表达式。而像math.Sin(math.Pi/4)
这种是函数调用,其值是在程序运行时才会得到,而不是在编译时。itoa
自动推导不属于函数调用,是由编译器实现的,因此也能用于常量的初始化。
ps:这一点在《Effective Go》中也有提到。经典的书还是要常翻常新啊
4. 指针对象也能够被JSON格式化。
这个主要利用到了Go能够对指针隐式转换。
对于隐式转换的使用,最常见的就是方法的接受者可以是指针也可以不是。如果一个对象是不是指针对象,但它有指针接受者的方法,那么其也可以使用该方法。
一句话总结就是无论什么的变量是普通的类型还是指针类型,或者实现的方法的接收器是普通类型还是指针类型,都可以通过点.来访问定义的方法
type MyInt int
// 接受器i是一个指针类型
func (i *MyInt) pAdd(x int) MyInt {
// 因为x和i虽然底层变量是一样的,但是其实是两种不同的变量了,所以不能直接相加,详见2.5类型
return *i + MyInt(x)
}
// 接收器i只是一个普通类型
func (i MyInt) Add(x int) MyInt {
return i + MyInt(x)
}
func main() {
i := MyInt(20)
pi := &i
// 以下都正确
fmt.Println(i.Add(1)) // 21
fmt.Println(i.pAdd(2)) // 22
fmt.Println(pi.Add(3)) // 23
fmt.Println(pi.pAdd(4)) // 24
}
4. nil只能赋值给指针、channel、func、interface、map或slice类型的变量。如果将nil赋值给其他变量的时候将会引发panic。
5. 使用声明语句声明空切片
var num1 []int
m2 := make([]int, 0)
对上面的两种变量使用append
,len
,cap
效果是一样的。