Data
分配
通过new和make分配空间:
- new分配空间,返回指针
- make可以进行生成slices,maps,channels,返回类型
package data_test import "testing" func TestCreateslices(t *testing.T) { s := make([]string, 3) s[0] = "c" s[1] = "a" s[2] = "o" t.Log(s) } func TestCreatemap(t *testing.T) { m := make(map[string]int) m["k1"] = 1 m["k2"] = 2 t.Log(m) } func TestCreatechannel(t *testing.T) { messages := make(chan string) go func() { messages <- "ping" }() msg := <-messages t.Log(msg) }
数组(Arrays)和切片(Slices)
go中更推荐使用切片而不是数组。
- 数组长度固定
- 切片可以动态调整容量(cap)
package data_test import "testing" func TestCreatearray(t *testing.T) { a := [...]int{1, 2, 3, 4} t.Log(a) s := make([]int, 4) s = a[0:4] t.Log(s) s = append(s, 5) t.Log(a) t.Log(s) } === RUN TestCreatearray f:\GO\go_test\data\data_test.go:29: [1 2 3 4] f:\GO\go_test\data\data_test.go:32: [1 2 3 4] f:\GO\go_test\data\data_test.go:34: [1 2 3 4] f:\GO\go_test\data\data_test.go:35: [1 2 3 4 5] --- PASS: TestCreatearray (0.00s)
二维切片(Two-dimensional Slices)
下面是二位数组和二位切片的示例。
type Transform [3][3]float64 // A 3x3 array, really an array of arrays. type LinesOfText [][]byte // A slice of byte slices.
Maps
key,value形式的数据结构,key可以是整数,浮点数,复数,字符串,指针,接口,结构体,数组。
切片不能做为key值由于他是变化的。
获取map中value, 可以通过以下方式,可以通过ok值判断,键值对是否存在。
... if seconds, ok := timeZone[tz]; ok { return seconds } log.Println("unknown time zone:", tz) return 0
Printing
打印方面类似C语言,主要存放在fmt包中,fmt.Printf
, fmt.Fprintf
, fmt.Sprintf
go by example的 String Formatting
package print_test import ( "fmt" "os" "testing" ) func TestPrintstring(t *testing.T) { type point struct { x, y int } p := point{1, 2} fmt.Printf("%v\n", p) fmt.Printf("%+v\n", p) fmt.Printf("%#v\n", p) fmt.Printf("%T\n", p) fmt.Printf("%t\n", true) fmt.Printf("%d\n", 123) fmt.Printf("%b\n", 14) fmt.Printf("%c\n", 33) fmt.Printf("%x\n", 456) fmt.Printf("%f\n", 78.9) fmt.Printf("%e\n", 1234000000.0) fmt.Printf("%E\n", 1234000000.0) fmt.Printf("%s\n", "\"string\"") fmt.Printf("%q\n", "\"string\"") fmt.Printf("%x\n", "hex this") fmt.Printf("%p\n", &p) fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45) fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45) fmt.Printf("|%6s|%6s|\n", "foo", "b") fmt.Printf("|%-6s|%-6s|\n", "foo", "b") s := fmt.Sprintf("a %s\n", "string") fmt.Printf(s) fmt.Fprintf(os.Stderr, "an %s\n", "error") } === RUN TestPrintstring {1 2} {x:1 y:2} print_test.point{x:1, y:2} print_test.point true 123 1110 ! 1c8 78.900000 1.234000e+09 1.234000E+09 "string" "\"string\"" 6865782074686973 0xc00001a360 | 1.20| 3.45| |1.20 |3.45 | | foo| b| |foo |b | a string an error --- PASS: TestPrintstring (0.00s)
初始化(Initialization)
- 常量
- 变量
- init函数: 可以在这个函数中做一些初始化的操作。
package init_test import ( "fmt" "os" "testing" ) type ByteSize float64 const ( _ = iota KB ByteSize = 1 << (10 * iota) MB GB TB PB EB ZB YB ) func (b ByteSize) String() string { switch { case b >= YB: return fmt.Sprintf("%.2fYB", b/YB) case b >= ZB: return fmt.Sprintf("%.2fZB", b/ZB) case b >= EB: return fmt.Sprintf("%.2fEB", b/EB) case b >= PB: return fmt.Sprintf("%.2fPB", b/PB) case b >= TB: return fmt.Sprintf("%.2fTB", b/TB) case b >= GB: return fmt.Sprintf("%.2fGB", b/GB) case b >= MB: return fmt.Sprintf("%.2fMB", b/MB) case b >= KB: return fmt.Sprintf("%.2fKB", b/KB) } return fmt.Sprintf("%.2fB", b) } func TestConst(t *testing.T) { t.Log(ByteSize(10240)) t.Log(ByteSize(YB)) t.Log(ByteSize(1000)) } func TestVarialbes(t *testing.T) { var ( home = os.Getenv("HOMEPATH") user = os.Getenv("USERNAME") gopath = os.Getenv("GOPATH") ) t.Log(home) t.Log(user) t.Log(gopath) } func init() { fmt.Fprintf(os.Stdout, "an %s\n", "init") }
方法
指针vs值
golang中指针也用.而不使用->, 用指针减少函数传递时的内存拷贝, 对原有引用数据有影响。
package method_test import ( "testing" ) type ByteSlice []byte func TestValuesAppend(t *testing.T) { var s ByteSlice x := ByteSlice{1, 2, 3, 4} s = s.Append(x) t.Log(s) y := ByteSlice{5, 6, 7, 8} s = s.Append(y) t.Log(s) t.Log(x) } func (slice ByteSlice) Append(data ByteSlice) ByteSlice { sliceLen := len(slice) if sliceLen+len(data) > cap(slice) { newSlice := make(ByteSlice, (sliceLen + len(data)*2)) copy(newSlice, slice) slice = newSlice } slice = slice[0 : sliceLen+len(data)] copy(slice[sliceLen:], data) return slice } func (p *ByteSlice) AppendPoint(data ByteSlice) { sliceLen := len(*p) if sliceLen+len(data) > cap(*p) { newSlice := make(ByteSlice, (sliceLen + len(data)*2)) copy(newSlice, *p) *p = newSlice } *p = (*p)[0 : sliceLen+len(data)] copy((*p)[sliceLen:], data) } func TestValuesAppendPoint(t *testing.T) { var s *ByteSlice x := ByteSlice{1, 2, 3, 4} s = &x t.Log(s) y := []byte{5, 6, 7, 8} s.AppendPoint(y) t.Log(s) t.Log(x) } === RUN TestValuesAppend f:\GO\go_test\method\method_test.go:13: [1 2 3 4] f:\GO\go_test\method\method_test.go:17: [1 2 3 4 5 6 7 8] f:\GO\go_test\method\method_test.go:18: [1 2 3 4] --- PASS: TestValuesAppend (0.00s) PASS ok loop/method 0.644s === RUN TestValuesAppendPoint f:\GO\go_test\method\method_test.go:49: &[1 2 3 4] f:\GO\go_test\method\method_test.go:53: &[1 2 3 4 5 6 7 8] f:\GO\go_test\method\method_test.go:54: [1 2 3 4 5 6 7 8] --- PASS: TestValuesAppendPoint (0.00s) PASS ok loop/method 0.114s
可以通过return或者指针两种方式更新切片的值。另外,对于结构定义的方法通过指针和结构都可以调用, 只是如果方法定义是使用结构模式 func (p struct XX) funcXX(xx), 那么参数传入方式时会进行结构复制,使用指针 func (p *struct XX) funcXX(xx)则不会。
参考及引用
Photo by Philippe Donn from Pexels
https://golang.org/doc/effective_go
Comments are closed.