翻译自 https://gobyexample.com/

Go by Example

Go is an open source programming language designed for building simple, fast, and reliable software.

Go by Example is a hands-on introduction to Go using annotated example programs. Check out the first example or browse the full list below.

Go by Example: Errors

golang中通过显式、单独的返回值来标识错误是一种常用的语言习惯。这与java和ruby等语言中使用的异常或C语言中有时使用重载单个返回值/错误是不同的。golang的这种处理方式很容易获取方法中返回的错误并且与其他没有返回错误的情况有相同的语句结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package main

import "errors"
import "fmt"

// 按照惯例,错误一般作为最后一个返回值,并且是内置的error类型
// errors.New创建一个以给定字符串为值的error
func f1(arg int) (int, error) {
if arg == 42 {
return -1, errors.New("Can't work with 42")
}

// nil标识没有错误返回
return arg + 3, nil
}

// 也可以通过定义一个实现了Error方法的类型作为error类型
// 该Error方法会打印出struct的两个变量
type argError struct {
arg int
prob string
}
func (e *argError) Error() string {
return fmt.Spintf("%d - %s", e.arg, e.prob)
}

// 使用&argError构造一个struct,作为error类型值返回
func f2(arg int) (int, error) {
if arg == 42 {
return -1, &argError{arg, "can't work with it"}
}

return arg + 3, nil
}

func main() {
// 下面的两个循环测试了两个会返回error值的函数
for _, i := range []int{7, 42} {
if r, e := f1(i); e != nil {
fmt.Println("f1 failed: ", e)
} else {
fmt.Println("f1 worked:", r)
}
}
for _, i := range []int{7, 42} {
if r, e := f2(i); e != nil {
fmt.Println("f2 failed:", e)
} else {
fmt.Println("f2 worked:", r)
}
}

// 如果要使用返回的自定义error数据,你需用断言的方式判断该返回值是自定义error的一个实例
_, e := f2(42)
if ae, ok := e.(*argError); ok {
fmt.Println(ae.arg)
fmt.Println(ae.prob)
}
}
1
2
3
4
5
6
7
$ go run errors.go
f1 worked: 10
f1 failed: can\'t work with 42
f2 worked: 10
f2 failed: 42 - can\'t work with it
42
can\'t work with it

延伸阅读:Error handling and Go

原文链接:Go by Example: Errors

翻译自 https://gobyexample.com/

Go by Example

Go is an open source programming language designed for building simple, fast, and reliable software.

Go by Example is a hands-on introduction to Go using annotated example programs. Check out the first example or browse the full list below.

Go by Example: Interfaces

golang中接口被定义为一系列方法的集合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package main

import "fmt"
import "math"

// 定义一个基本几何图形的接口
type geometry interface {
area() float64
perim() float64
}

// 定义两个结构体 rect和circle 实现这个接口
type rect struct {
width, height float64
}

type circle struct {
radius float64
}

// golang中实现一个接口类型,只需实现该接口所有的方法
func (r rect) area() float64 {
return r.width * r.height
}

func (r rect) perim() float64 {
return 2*r.width + 2*r.height
}

func (c circle) area() float64 {
return math.Pi * c.radius * c.radius
}

func (c circle) perim() float64 {
return 2 * math.Pi * c.radius
}

// 如果一个变量实现了一个接口类型,则该变量可以调用接口所有的方法
func measure(g geometry) {
fmt.Println(g)
fmt.Println(g.area())
fmt.Println(g.perim())
}

func main() {
r := rect{width: 3, height: 4}
c := circle{radius: 5}

measure(r)
measure(c)
}
1
2
3
4
5
6
7
$ go run interfaces.go
{3 4}
12
14
{5}
78.53981633974483
31.41592653589793

延伸阅读: how-to-use-interfaces-in-go

原文链接:Go by Example: Interfaces

翻译自 https://gobyexample.com/

Go by Example

Go is an open source programming language designed for building simple, fast, and reliable software.

Go by Example is a hands-on introduction to Go using annotated example programs. Check out the first example or browse the full list below.

Go by Example: Methods

golang支持在结构体上定义方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import "fmt"

type rect struct {
width, height int
}

// 在rect的引用类型上定义一个area方法
func (r *rect) area() int {
return 2*r.width * 2*r.height
}

// 也可以将方法定义在结构体上
funv (r rect) perim() int {
return 2*r.width + 2*r.height
}

func main() {
r := rect{width: 10, height: 5}

// 直接使用结构体来调用两个方法
fmt.Println("area: ", r.area())
fmt.Println("perim: ", r.perim())

rp := &r

// golang会在方法调用时在结构体和引用之间自动转换,你可能希望使用指针来避免方法调用时的值传递,并且可以在方法内修改传入的结构体的值
fmt.Println("area: ", rp.area())
fmt.Println("perim: ", rp.perim())
}
1
2
3
4
5
$ go run methods.go 
area: 50
perim: 30
area: 50
perim: 30

原文链接:Go by Example: Methods

翻译自 https://gobyexample.com/

Go by Example

Go is an open source programming language designed for building simple, fast, and reliable software.

Go by Example is a hands-on introduction to Go using annotated example programs. Check out the first example or browse the full list below.

Go by Example: Structs

golang中定义结构体为一系列元素的集合,这对于将数据分组记录很有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main

import "fmt"

// 定义一个结构体,含有name和age两个字段
type person struct {
name string
age int
}

func main() {
// 实例化一个person结构体
fmt.Println(person{"Bob", 20})

// 也可以指定字段名赋值进行实例化
fmt.Println(person{name: "Alice", age: 30})

// 实例化为赋值的元素默认为零值
fmt.Println(person{name: "Fred"})

// 打印一个指向结构体的指针
fmt.Println(&person{name: "Ann", age: 40})

// 使用.操作符来操作结构体的字段
s := person{name: "Sean", age: 50}
fmt.Println(s.name)

// 也可以使用.操作符操作结构体指针的字段,此时指针会自动取消引用转化为结构体本身
sp := &s
fmt.Println(sp.age)

// 结构体的值是可变的
sp.age = 51
fmt.Println(sp.age)
}
1
2
3
4
5
6
7
8
$ go run structs.go
{Bob 20}
{Alice 30}
{Fred 0}
&{Ann 40}
Sean
50
51

原文链接:Go by Example: Structs

翻译自 https://gobyexample.com/

Go by Example

Go is an open source programming language designed for building simple, fast, and reliable software.

Go by Example is a hands-on introduction to Go using annotated example programs. Check out the first example or browse the full list below.

Go by Example: Pointers

golang支持指针,允许在程序中传递值和记录的引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import "fmt"

// 接收一个int类型参数。
// 对ival的赋值不会影响外部变量的值。
func zeroval(ival int) {
ival = 0
}

// 接收一个int指针类型的参数。
// 对*iptr的赋值操作会直接修改到iptr指针所指向内存的地址。
func zeroptr(iptr *int) {
*iptr = 0
}

func main() {
i := 1
fmt.Println("initial:", i)

// 传值。
zeroval(i)
fmt.Println("zeroval:", i)

// 传引用。
zeroptr(&i)
fmt.Println("zeroptr:", i)

// 打印指针指向的内存地址。
fmt.Println("pointer:", &i)
}
1
2
3
4
5
$ go run pointers.go
initial: 1
zeroval: 1
zeroptr: 0
pointer: 0x42131100

原文链接:Go by Example: Pointers

翻译自 https://gobyexample.com/

Go by Example

Go is an open source programming language designed for building simple, fast, and reliable software.

Go by Example is a hands-on introduction to Go using annotated example programs. Check out the first example or browse the full list below.

Go by Example: Recursion

golang也支持递归函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import "fmt"

// 定义一个函数fact递归调用自己直到参数变为0。
func fact(n int) int {
if n == 0 {
return 1
}

return n * fact(n-1)
}

func main() {
fmt.Println(fact(7))
}

原文链接:Go by Example: Recursion

翻译自 https://gobyexample.com/

Go by Example

Go is an open source programming language designed for building simple, fast, and reliable software.

Go by Example is a hands-on introduction to Go using annotated example programs. Check out the first example or browse the full list below.

Go by Example: Closures

golang支持匿名函数,可以用来构建闭包。当你需要定一个不需要命名的内连函数时匿名函数很有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import "fmt"

// 定义一个函数intSeq返回内部定义的一个匿名函数。
// 返回的函数通过返回变量i来结束并构建闭包。
func intSeq() func() int {
i := 0
return func() int {
i += 1
return i
}
}

func main() {
// 调用函数intSeq,并将其返回给变量nextInt。
// 该函数值使用自己拥有的变量i,i在我们调用nextInt时都会更新。
nextInt := intSeq()

// 调用nextInt函数
fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())

// 变量i的值独立于每个intSeq函数调用。
nextInts := intSeq()
fmt.Println(nextInts())
}
1
2
3
4
5
$ go run closures.go
1
2
3
1

原文链接:Go by Example: Closures

翻译自 https://gobyexample.com/

Go by Example

Go is an open source programming language designed for building simple, fast, and reliable software.

Go by Example is a hands-on introduction to Go using annotated example programs. Check out the first example or browse the full list below.

Go by Example: Variadic Functions

可以使用任意数量的参数来调用可变参数函数,如fmt.Println就是一个常用的可变参数函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import "fmt"

// 定义一个函数,可以接受任意数量的int值作为参数。
func sum(nums ...int) {
fmt.Print(nums, " ")
total := 0
for _, num := range nums {
total += num
}
fmt.Println(total)
}

func main() {
// 使用独立的参数调用。
sum(1, 2)
sum(1, 2, 3)

// 使用相应类型的slice调用可变参数函数。func(slice...)。
nums := []int{1, 2, 3, 4}
sum(nums...)
}
1
2
3
4
$ go run variadic-functions.go 
[1 2] 3
[1 2 3] 6
[1 2 3 4] 10

原文链接:Go by Example: Variadic Functions

翻译自 https://gobyexample.com/

Go by Example

Go is an open source programming language designed for building simple, fast, and reliable software.

Go by Example is a hands-on introduction to Go using annotated example programs. Check out the first example or browse the full list below.

Go by Example: Multiple Return Values

golang原生支持多个返回值,这在golang的编程习惯中很常见,如函数同时返回返回值和error。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import "fmt"

// (int, int)标识函数会返回两个int值
func vals() (int, int) {
return 3, 7
}

func main() {
// 使用两个变量接收两个返回值
a, b := vals()
fmt.Println(a)
fmt.Println(b)

// 使用‘_’可以忽略掉该返回值
_, c := vals()
fmt.Println(c)
}
1
2
3
4
$ go run multiple-return-values.go
3
7
7

原文链接:Go by Example: Multiple Return Values

翻译自 https://gobyexample.com/

Go by Example

Go is an open source programming language designed for building simple, fast, and reliable software.

Go by Example is a hands-on introduction to Go using annotated example programs. Check out the first example or browse the full list below.

Go by Example: Functions

函数是golang的核心。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import "fmt"

// 接收两个int类型的参数,并返回两者之和。
// golang的函数需要显式的return。
func plus(a int, b int) int {
return a + b
}

// 多个同样类型的参数简便的定义。
func plusPlus(a, b, c int) int {
return a + b + c
}

func main() {
res := plus(1, 2)
fmt.Println("1+2=", res)

res = plusPlus(1, 2, 3)
fmt.Println("1+2+3=", res)
}
1
2
3
$ go run functions.go 
1+2 = 3
1+2+3 = 6

原文链接:Go by Example: Functions