Golang 通关初级(2)

目录(?)[+]

原文

https://tour.golang.org/welcome/1

指针

Go 具有指针。 指针保存了变量的内存地址。

类型 *T 是指向 T 类型值的指针。其零值为 nil 。

var p *int
   
   
  • 1
  • 1

& 操作符会生成一个指向其操作数的指针。

i := 42
p = &i
   
   
  • 1
  • 2
  • 1
  • 2
  • 操作符表示指针指向的底层值。
fmt.Println(*p) // 通过指针 p 读取 i
*p = 21         // 通过指针 p 设置 i
   
   
  • 1
  • 2
  • 1
  • 2

这也就是通常所说的“间接引用”或“重定向”。

与 C 不同,Go 没有指针运算。

package main

import (
    "fmt"
)

func main() {
    a, b := 12, 33

    p := &a
    fmt.Printf("p = %v, *p = %v\n", p, *p)

    *p = *p * 2
    fmt.Printf("p = %v, *p = %v\n", p, *p)

    p = &b
    fmt.Printf("p = %v, *p = %v\n", p, *p)

}

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

输出:

p = 0xc082004258, *p = 12
p = 0xc082004258, *p = 24
p = 0xc082004280, *p = 33
   
   
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

结构体

一个结构体( struct )就是一个字段的集合。

(而 type 声明就是定义类型的。)

package main

import (
    "fmt"
)

type People struct {
    name string
    age  int
}

func main() {
    fmt.Println(People{"Afra", 22})
}

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

输出:

{Afra 22}
   
   
  • 1
  • 1

结构体字段 
结构体字段使用点号来访问。

package main

import (
    "fmt"
)

type People struct {
    name string
    age  int
}

func main() {
    me := People{"Afra", 22}
    fmt.Printf("name = %v, age = %v\n", me.name, me.age)
}

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

输出:

name = Afra, age = 22
   
   
  • 1
  • 1

结构体指针 
结构体字段可以通过结构体指针来访问。

如果我们有一个指向结构体的指针 p ,那么可以通过 (*p).X 来访问其字段 X 。 不过这么写太啰嗦了,所以语言也允许我们使用隐式间接引用,直接写 p.X 就可以。

package main

import (
    "fmt"
)

type People struct {
    name string
    age  int
}

func main() {
    me := People{"Afra", 22}
    p := &me
    fmt.Printf("name = %v, age = %v\n", p.name, p.age)
}

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

输出:

name = Afra, age = 22
   
   
  • 1
  • 1

结构体文法 
结构体文法通过直接列出字段的值来新分配一个结构体。

使用 Name: 语法可以仅列出部分字段。(字段名的顺序无关。)

特殊的前缀 & 返回一个指向结构体的指针。

package main

import (
    "fmt"
)

type People struct {
    name string
    age  int
}

var (
    a = People{"Afra", 22}
    b = People{age: 22}
    c = People{name: "Victor"}
    d = People{}
    e = &People{"Victor", 87}
)

func main() {
    fmt.Println(a, b, c, d, e)
}

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

输出:

{Afra 22} { 22} {Victor 0} { 0} &{Victor 87}
   
   
  • 1
  • 1

数组

类型 [n]T 表示拥有 n 个 T 类型的值的数组。

表达式

var a [10]int 
会将变量 a 声明为拥有有 10 个整数的数组。

数组的长度是其类型的一部分,因此数组不能改变大小。 这看起来是个限制,不过没关系, Go 提供了更加便利的方式来使用数组。

package main

import (
    "fmt"
)

func main() {
    var a [2]string
    a[0] = "Afra55"
    a[1] = "Victor"

    fmt.Println(a[0], a[1])
    fmt.Println(a)

    b := [6]int{1, 2, 4, 5, 6, 6}
    fmt.Println(b)
}

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

输出:

Afra55 Victor
[Afra55 Victor]
[1 2 4 5 6 6]
   
   
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

切片

每个数组的大小都是固定的。 而切片则为数组元素提供动态大小的、灵活的视角。 在实践中,切片比数组更常用。

类型 []T 表示一个元素类型为 T 的切片。

以下表达式为数组 a 的前五个元素创建了一个切片。

a[0:5]
   
   
  • 1
  • 1
package main

import (
    "fmt"
)

func main() {
    source := [6]int{1, 2, 3, 5, 4}

    var s []int = source[2:6]
    fmt.Println(s)
}

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

输出:

[3 5 4 0]
   
   
  • 1
  • 1

切片就像数组的引用

切片并不存储任何数据, 它只是描述了底层数组中的一段。

更改切片的元素会修改其底层数组中对应的元素。

与它共享底层数组的切片都会观测到这些修改。

package main

import (
    "fmt"
)

func main() {
    source := [6]int{1, 2, 3, 5, 4}

    var s []int = source[2:6]
    fmt.Println(s)
    source[5] = 7
    fmt.Println(s)
    s[0] = 88
    fmt.Println(source)
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

输出:

[3 5 4 0]
[3 5 4 7]
[1 2 88 5 4 7]
   
   
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

切片文法 
切片文法类似于没有长度的数组文法。

这是一个数组文法:

[3]bool{true, true, false}
   
   
  • 1
  • 1

下面这样则会创建一个和上面相同的数组,然后构建一个引用了它的切片:

[]bool{true, true, false}
   
   
  • 1
  • 1
package main

import (
    "fmt"
)

func main() {
    // a 是切片
    a := []int{12, 5, 3, 6, 8, 6}

    fmt.Println(a)

    // b 是个切片
    b := []struct {
        age  int
        name string
    }{
        {1, "xx"}, {2, "xxx"}, {3, "xxxx"},
    }

    fmt.Println(b)
}

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

输出:

[12 5 3 6 8 6]
[{1 xx} {2 xxx} {3 xxxx}]
   
   
  • 1
  • 2
  • 1
  • 2

切片的默认行为 
在进行切片时,你可以利用它的默认行为来忽略上下界。

切片下界的默认值为 0 ,上界则是该切片的长度。

对于数组:

var a [10]int
   
   
  • 1
  • 1

来说,以下切片是等价的:

a[0:10]
a[:10]
a[0:]
a[:]
   
   
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
package main

import (
    "fmt"
)

func main() {
    // a 是切片
    a := []int{12, 5, 3, 6, 8, 6}

    a = a[1:6]
    fmt.Println(a)

    a = a[:3]
    fmt.Println(a)

    a = a[2:]
    fmt.Println(a)
}

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
<ul class="pre-numbering%
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值