从Two-dimensional slices开始,使用中文版的effctive_go学习
https://www.kancloud.cn/kancloud/effective/72207
Data:
二维切片:
- Go的数组和切片都是一维的。要创建等价的二维数组或者切片,需要定义一个数组的数组或者切片的切片。
Maps:
- Map是一种方便,强大的内建数据结构,其将一个类型的值(key)与另一个类型的值(element或value) 关联一起。
- key可以为任何 定义了等于操作符 的类型,例如整数,浮点和复数,字符串,指针,接口(只要其动态类型支持等于操作),结构体和数组。
- 切片不能 作为map的key,因为它们没有定义等于操作。和切片类似,map持有对底层数据结构的引用。如果将map传递给函数,其对map的内容做了改变,则这些改变对于调用者是可见的。
1 | attended := map[string]bool{ |
- 如果只测试是否在map中存在,而不关心实际的值,你可以将通常使用变量的地方换成空白标识符(_)
1 | _, present := timeZone[tz] |
- 要删除一个map项,使用delete内建函数,其参数为map和要删除的key。即使key已经不在map中,这样做也是安全的。
1 | delete(timeZone, "PDT") // Now on Standard Time |
- map不太好判断是否存在某个key,如果key不存在返回的对应类型的零值,如果已有key的value恰好为零值会导致误判
打印输出
- Go中的格式化打印使用了与C中printf家族类似的风格,不过更加丰富和通用。这些函数位于fmt程序包中,并具有大写的名字:fmt.Printf,fmt.Fprintf,fmt.Sprintf等等。字符串函数(Sprintf等)返回一个字符串,而不是填充到提供的缓冲里。
- 你不需要提供一个格式串。对每个Printf,Fprintf和Sprintf,都有另外一对相应的函数,例如Print和Println。这些函数不接受格式串,而是为每个参数生成一个缺省的格式。Println版本还会在参数之间插入一个空格,并添加一个换行,而Print版本只有当两边的操作数都不是字符串的时候才增加一个空格。在这个例子中,每一行都会产生相同的输出。
- 格式化打印函数fmt.Fprint等,接受的第一个参数为任何一个实现了io.Writer接口的对象;变量os.Stdout和os.Stderr是常见的实例。
- 如果只是想要缺省的转换,像十进制整数,你可以使用 通用格式%v(代表“value”);这正是Print和Println所产生的结果。而且,这个格式可以打印任意的的值,甚至是数组,切片,结构体和map。
- 当打印一个结构体时,带修饰的格式 %+v会将结构体的域使用它们的名字进行注解,对于任意的值,格式%#v会按照完整的Go语法打印出该值。
- 还可以通过 %q 来实现带引号的字符串格式,用于类型为 string或[]byte 的值。格式 %#q 将尽可能的使用反引号。(格式%q还用于整数和符文,产生一个带单引号的符文常量。)
- %x 用于字符串,字节数组和字节切片,以及整数,生成一个 长的十六进制字符串,并且如果在格式中 有一个空格(% x),其将会在 字节中插入空格。
- 不要在Sprintf里面调用接收者的String方法,否则会造成无穷递归,如下。只有%s匹配才会调用MyString的String方法
1 | type MyString string |
- 另一种打印技术,是将一个打印程序的参数直接传递给另一个这样的程序。Printf的签名使用了类型…interface{}作为最后一个参数,来指定在格式之后可以出现任意数目的(任意类型的)参数。
append内建函数:
- 其中T为任意给定类型的占位符。你在Go中是无法写出一个类型T由调用者来确定的函数。这就是为什么append是内建的:它需要编译器的支持。append所做的事情是将元素添加到切片的结尾,并返回结果。
1 | func append(slice []T, elements ...T) []T |
- 如果想要在append中把一个slice添加到另一个slice要怎么做?在调用点使用 “…”,
1 | x := []int{1,2,3} |
- 可以看出 “…” 的作用是,把一个slice转为对应的type,作为一个参数列表进行传递