DevilKing's blog

冷灯看剑,剑上几分功名?炉香无需计苍生,纵一穿烟逝,万丈云埋,孤阳还照古陵

0%

Golang-101-hacks

Use govendor to implement vendoring

利用govendor部分,进行相关的依赖保证

1
2
3
4
govendor init

govendor add +external

这样我们在进行go get的时候,可以将相关的依赖同时下载下来。

short variable declaration

1
i := 10

一般都会产生一个新的变量,这样要防止全局变量和局部变量之间的区别

nil silce vs nil map

Slice and map are all reference types in Go, and their default values are nil

1
2
var s1 []int
s2 := []int{}

上述两种方式,第二种的命名s2非nil,但同样长度为0

init function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var WhatIsThe = AnswerToLife()

func AnswerToLife() int {
return 42
}

func init() {
WhatIsThe = 0
}

func main() {
if WhatIsThe == 0 {
fmt.Println("It's all a lie.")
}
}

上述初始化的顺序,AnswerToLife() -> init() -> main()

The internals of slice

包含3部分

  • pointer

  • length

  • capacity

gdb

采用gdb调试golang代码?

Pass slice as a function argument

In Go, the function parameters are passed by value. With respect to use slice as a function argument, that means the function will get the copies of the slice: a pointer which points to the starting address of the underlying array, accompanied by the length and capacity of the slice.

golang中采用的值传递的方式,如果需要改变相关的值的话,需要传递相关的指针?

但针对array来说,

since in Go, the function argument is passed by “value”, so if you use an array as a function argument, the function just does the operations on the copy of the original copy.

关于slice和array之间的区别问题

In Go, array is a fixed length of continuous memory with specified type, while slice is just a reference which points to an underlying array.

可以从array来创建slice,但反之不行。。

Two-dimensional slice

1
2
3
4
5
6
7
8
9
10
11
func main() {
s := make([][]int, 2)
fmt.Println(len(s), cap(s), &s[0])

s[0] = []int{1, 2, 3}
fmt.Println(len(s[0]), cap(s[0]), &s[0][0])

s[1] = make([]int, 3, 5)
fmt.Println(len(s[1]), cap(s[1]), &s[1][0])
}

二维数组?

Reallocating underlying array of slice

在append的使用过程中,可能会在未通知你的情况下改变数组

Type assertion and type switch

1
2
3
4
5
6
if v, ok := v.(string); ok {
fmt.Printf("The value of v is: %v", v)
} else {
fmt.Println("Oops, it is not a string!")
}

采用这种方式,方式在type assertion的过程中发生的panic错误

io.reader

1
2
3
4
5

p := make([]byte, 4)
for {
if n, err := file.Read(p); n > 0 {
fmt.Printf("Read %s\n", p[:n])

采用这种方式来进行file.read部分

bufferio也提供read的功能

1
2
3
4
r := bufio.NewReader(f)
for {
if s, err := r.ReadSlice('\n'); err == nil || err == io.EOF {
fmt.Printf("%s", s)

以及采用s := bufio.NewScanner(f)的Scan的方式

Data race

1
2
3

go run -race main.go

采用这种方式,可以进行race detector部分,

Sort

只要实现Len, Swap,以及Less的功能,即可针对interface进行sort操作

close channel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main() {
ch := make(chan int)
go func(chan int) {
for _, v := range []int{1, 2} {
ch <- v
}
close(ch)
}(ch)

for v := range ch {
fmt.Println(v)
}
fmt.Println("The channel is closed.")
}

We can see close(ch) statement in another goroutine make the loop in main goroutine end.

这部分的close操作的保证,有些奇怪?

error vs errors

errors核心部分的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
package errors

func New(text string) error {
return &errorString{text}
}

type errorString struct {
s string
}

func (e *errorString) Error() string {
return e.s
}

channel types

1
var v <-chan T

read-only channel

1
var v chan<- T

write-only channel

nil channel vs closed channel

The Go’s built-in close function can be used to close the channel which must not be receive-only, and it should always be executed by sender, not receiver. Closing a nil channel will cause panic.

关于内置的close方法

select

关于select操作部分

The select operation will check which case branch can be run, that means the send or receive action can be executed successfully. If more than one case are ready now, the select will randomly choose one to execute.

Need not close every channel

A channel that the garbage collector determines to be unreachable will have its resources reclaimed whether or not it is closed