未使用的imports
可以注释掉或者加下划线'_',否则,编译报错
package main
import (
- "fmt"
"log"
"time"
)
var _ = log.Println
func main() {
_ = time.Now
}
使用简式声明重复声明变量
你不能在一个单独的声明中重复声明一个变量,但在多变量声明中这是允许的,其中至少要有一个新的声明变量。
重复变量需要在相同的代码块内,否则你将得到一个隐藏变量。
Fails:
package main
func main() {
one := 0
one := 1 //error
}
Compile Error:
/tmp/sandbox706333626/main.go:5: no new variables on left side of :=
Works:
package main
func main() {
one := 0
one, two := 1,2
one,two = two,one
}
用 nil 初始化slice和map
在一个“nil”的slice中添加元素是没问题的,但对一个map做同样的事将会生成一个运行时的panic。
Works:
package main
func main() {
var s []int
s = append(s,1)
}
Fails:
package main
func main() {
var m map[string]int
m["one"] = 1 //error
}
map 的容量
你可以在map创建时指定它的容量,但你无法在map上使用cap()函数。
package main
func main() {
m := make(map[string]int,99)
cap(m) //error
}
Compile Error:
/tmp/sandbox326543983/main.go:5: invalid argument m (type map[string]int) for cap
字符串不能初始化为 "nil"
这对于经常使用“nil”分配字符串变量的开发者而言是个需要注意的地方。
二维数组的创建
你可以使用纯一维数组、“独立”切片的切片,“共享数据”切片的切片来构建动态的多维数组。
如果你使用纯一维的数组,你需要处理索引、边界检查、当数组需要变大时的内存重新分配。
使用“独立”slice来创建一个动态的多维数组需要两步。首先,你需要创建一个外部的slice。然后,你需要分配每个内部的slice。内部的slice相互之间独立。你可以增加减少它们,而不会影响其他内部的slice。
package main
func main() {
x := 2
y := 4
table := make([][]int,x)
for i:= range table {
table[i] = make([]int,y)
}
}
使用“共享数据”slice的slice来创建一个动态的多维数组需要三步。首先,你需要创建一个用于存放原始数据的数据“容器”。然后,你再创建外部的slice。最后,通过重新切片原始数据slice来初始化各个内部的slice。
package main
import "fmt"
func main() {
h, w := 2, 4
raw := make([]int,h*w)
for i := range raw {
raw[i] = i
}
fmt.Println(raw,&raw[4])
//prints: [0 1 2 3 4 5 6 7] <ptr_addr_x>
table := make([][]int,h)
for i:= range table {
table[i] = raw[i*w:i*w + w]
}
fmt.Println(table,&table[1][0])
//prints: [[0 1 2 3] [4 5 6 7]] <ptr_addr_x>
}
判断map中节点是否存在
检测给定map中的记录是否存在的最可信的方法是,通过map的访问操作,检查第二个返回的值。
package main
import "fmt"
func main() {
x := map[string]string{"one":"a","two":"","three":"c"}
if _,ok := x["two"]; !ok {
fmt.Println("no entry")
}
}
string的修改
如果是ASCII码,要转换成[]byte,如果是unicode,要转化成rune byte
[]byte的方法
package main
import "fmt"
func main() {
x := "text"
xbytes := []byte(x)
xbytes[0] = 'T'
fmt.Println(string(xbytes)) //prints Text
}
string 与 rune byte 的关系
在Go当中 string底层是用byte数组存的,并且是不可以改变的。
例如 s:="Go编程" fmt.Println(len(s)) 输出结果应该是8因为中文字符是用3个字节存的。
len(string(rune('编')))的结果是3
如果想要获得我们想要的情况的话,需要先转换为rune切片再使用内置的len函数
fmt.Println(len([]rune(s)))
结果就是4了。
所以用string存储unicode的话,如果有中文,按下标是访问不到的,因为你只能得到一个byte。 要想访问中文的话,还是要用rune切片,这样就能按下表访问。
判断字符串是否为UTF8
为了知道字符串是否是UTF8,你可以使用“unicode/utf8”包中的ValidString()函数。
求字符串长度
ASCII:len();
unicode:RuneCountInString()。实际上,RuneCountInString()求的是rune的个数,不是绝对的字符个数,因为一个字符可能占多个rune
在多行的Slice、Array和Map语句中遗漏逗号
Fails:
package main
func main() {
x := []int{
1,
2 //error
}
_ = x
}
Works:
package main
func main() {
x := []int{
1,
2,
}
x = x
y := []int{3,4,} //no error
y = y
}
当你把声明折叠到单行时,如果你没加末尾的逗号,你将不会得到编译错误
log.Fatal和log.Panic不仅仅是Log
Logging库一般提供不同的log等级。与这些logging库不同,Go中log包在你调用它的Fatal()和Panic()函数时,可以做的不仅仅是log。当你的应用调用这些函数时,Go也将会终止应用 🙂