前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go语言入门基础

Go语言入门基础

作者头像
李海彬
发布2018-03-27 12:04:46
6410
发布2018-03-27 12:04:46
举报
文章被收录于专栏:Golang语言社区

指针

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

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

  1. var p *int

复制代码

& 符号会生成一个指向其作用对象的指针。

  1. i := 42
  2. p = &i

复制代码

*符号表示指针指向的底层的值。

  1. fmt.Println(*p) // 通过指针 p 读取 i
  2. *p = 21         // 通过指针 p 设置 i

这也就是通常所说的“间接引用”或“非直接引用”。

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

代码语言:javascript
复制
package main

import "fmt"

func main() {

    i, j := 42, 2701

    p := &i         // point to i

    fmt.Println(*p) // read i through the pointer

    *p = 21         // set i through the pointer

    fmt.Println(i)  // see the new value of i

    p = &j         // point to j

    *p = *p / 37   // divide j through the pointer

    fmt.Println(j) // see the new value of j

}

结构体

一个结构体( struct )就是一个字段的集合。(而 type 的含义跟其字面意思相符。)

代码语言:javascript
复制
package main

import "fmt"

type Vertex struct {

    X int

    Y int

}

func main() {

    fmt.Println(Vertex{1, 2})

}

结构体字段

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

代码语言:javascript
复制
package main

import "fmt"

type Vertex struct {

    X int

    Y int

}

func main() {

    v := Vertex{1, 2}

    v.X = 4

    fmt.Println(v.X)

}

结构体指针

结构体字段可以通过结构体指针来访问。 通过指针间接的访问是透明的。

代码语言:javascript
复制
package main

import "fmt"

type Vertex struct {

    X int

    Y int

}

func main() {

    v := Vertex{1, 2}

    p := &v

    p.X = 1e9

    fmt.Println(v)

}

结构体符文

结构体符文表示通过结构体字段的值作为列表来新分配一个结构体。 使用 Name: 语法可以仅列出部分字段。(字段名的顺序无关。) 特殊的前缀 & 返回一个指向结构体的指针。

代码语言:javascript
复制
package main

import "fmt"

type Vertex struct {

    X, Y int

}

var (

    v1 = Vertex{1, 2}  // 类型为 Vertex

    v2 = Vertex{X: 1}  // Y:0 被省略

    v3 = Vertex{}      // X:0 和 Y:0

    p  = &Vertex{1, 2} // 类型为 *Vertex

)

func main() {

    fmt.Println(v1, p, v2, v3)

}

数组

类型 [n]T 是一个有 n 个类型为 T 的值的数组。

表达式

  1. var a [10]int

定义变量 a 是一个有十个整数的数组。

数组的长度是其类型的一部分,因此数组不能改变大小。这看起来是一个制约,但是请不要担心; Go 提供了更加便利的方式来使用数组。

切片(slice)

一个 slice 会指向一个序列的值,并且包含了长度信息。

[]T 是一个元素类型为 T 的 切片(slice)。

len(s)返回 slice s的长度。

代码语言:javascript
复制
package main

import "fmt"

func main() {

    s := []int{2, 3, 5, 7, 11, 13}

    fmt.Println("s ==", s)

    for i := 0; i < len(s); i++ {

        fmt.Printf("s[%d] == %d\n", i, s[i])

    }

}

切片(slice)的切片

切片(slice)可以包含任意的类型,包括另一个 slice。

代码语言:javascript
复制
package main

import (

    "fmt"

    "strings"

)

func main() {

    // Create a tic-tac-toe board.

    game := [][]string{

        []string{"_", "_", "_"},

        []string{"_", "_", "_"},

        []string{"_", "_", "_"},

    }

    // The players take turns.

    game[0][0] = "X"

    game[2][2] = "O"

    game[2][0] = "X"

    game[1][0] = "O"

    game[0][2] = "X"

    printBoard(game)

}

func printBoard(s [][]string) {

    for i := 0; i < len(s); i++ {

        fmt.Printf("%s\n", strings.Join(s[i], " "))

    }

}

对 slice 切片

slice 可以重新切片,创建一个新的 slice 值指向相同的数组。

表达式

  1. s[lo:hi]

表示从 lo 到 hi-1 的 slice 元素,含前端,不包含后端。因此

  1. s[lo:lo]

是空的,而

  1. s[lo:lo+1]

复制代码

有一个元素。

代码语言:javascript
复制
package main

import "fmt"

func main() {

    s := []int{2, 3, 5, 7, 11, 13}

    fmt.Println("s ==", s)

    fmt.Println("s[1:4] ==", s[1:4])

    // 省略下标代表从 0 开始

    fmt.Println("s[:3] ==", s[:3])

    // 省略上标代表到 len(s) 结束

    fmt.Println("s[4:] ==", s[4:])

}

复制代码

构造 slice

slice 由函数 make 创建。这会分配一个全是零值的数组并且返回一个 slice 指向这个数组:

  1. a := make([]int, 5)  // len(a)=5

复制代码

为了指定容量,可传递第三个参数到 make:

  1. b := make([]int, 0, 5) // len(b)=0, cap(b)=5
  2. b = b[:cap(b)] // len(b)=5, cap(b)=5
  3. b = b[1:]      // len(b)=4, cap(b)=4

参考以下示例代码 -

代码语言:javascript
复制
package main

import "fmt"

func main() {

    a := make([]int, 5)

    printSlice("a", a)

    b := make([]int, 0, 5)

    printSlice("b", b)

    c := b[:2]

    printSlice("c", c)

    d := c[2:5]

    printSlice("d", d)

}

func printSlice(s string, x []int) {

    fmt.Printf("%s len=%d cap=%d %v\n",

        s, len(x), cap(x), x)

}

nil slice

slice 的零值是 nil 。

一个 nil 的 slice 的长度和容量是 0。

代码语言:javascript
复制
package main

import "fmt"

func main() {

    var z []int

    fmt.Println(z, len(z), cap(z))

    if z == nil {

        fmt.Println("nil!")

    }

}

向 slice 添加元素

向 slice 的末尾添加元素是一种常见的操作,因此 Go 提供了一个内建函数 append 。 内建函数的文档对 append 有详细介绍。

  1. func append(s []T, vs ...T) []T

append 的第一个参数 s 是一个元素类型为 T 的 slice ,其余类型为 T 的值将会附加到该 slice 的末尾。

append 的结果是一个包含原 slice 所有元素加上新添加的元素的 slice。

如果 s 的底层数组太小,而不能容纳所有值时,会分配一个更大的数组。 返回的 slice 会指向这个新分配的数组。

代码语言:javascript
复制
package main

import "fmt"

func main() {

    var a []int

    printSlice("a", a)

    // append works on nil slices.

    a = append(a, 0)

    printSlice("a", a)

    // the slice grows as needed.

    a = append(a, 1)

    printSlice("a", a)

    // we can add more than one element at a time.

    a = append(a, 2, 3, 4)

    printSlice("a", a)

}

func printSlice(s string, x []int) {

    fmt.Printf("%s len=%d cap=%d %v\n",

        s, len(x), cap(x), x)

}

复制代码

范围(range)

for 循环的 range 格式可以对 slice 或者 map 进行迭代循环。

当使用 for 循环遍历一个 slice 时,每次迭代 range 将返回两个值。 第一个是当前下标(序号),第二个是该下标所对应元素的一个拷贝。

代码语言:javascript
复制
ackage main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main() {

    for i, v := range pow {

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

    }

}

可以通过赋值给 _ 来忽略序号和值。

如果只需要索引值,去掉 “ , value ” 的部分即可。

代码语言:javascript
复制
package main

import "fmt"

func main() {

    pow := make([]int, 10)

    for i := range pow {

        pow[i] = 1 << uint(i)

    }

    for _, value := range pow {

        fmt.Printf("%d\n", value)

    }

}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-07-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Golang语言社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档