借此机会,熟悉一下IDE的使用。用Go写几道PTA即可
Start from
数组
定义
var arrName[n]Type
arrName := [n]Type{...}
遍历
for index, value := range arrName{
fmt.Println(index, value)
}
切片
一个slice由三个部分构成:指针、长度和容量。指针指向第一个slice元素对应的底层数组元素的地址,要注意的是slice的第一个元素并不一定就是数组的第一个元素。长度对应slice中元素的数目;长度不能超过容量,容量一般是从slice的开始位置到底层数据的结尾位置。内置的len和cap函数分别返回slice的长度和容量。
定义
切片代表数组的一部分,我们有两种方法创建一个切片。
scores := []int{1,2,3,4}
大多数情况下我们并不知道切片的具体内容,因而这种方法用的较少。
scores := make([]int, 4)
创建了一个长度为4,容量为4的切片。这里的长度和容量和变长数组中用到的一样。初始化时,所有位置的值都是零。
我们可以使用append函数,往切片尾部添加数据。当切片的容量不够时,go会自动以两倍的速度扩展容量。
scores := make([]int, 4)
scores = append(scores, 5)
fmt.Println(cap(scores), scores)
此时,切片scores
的容量为8,长度为5;输出 :8 [0, 0, 0, 0, 5]
cap() 是内置函数,可以返回切片的容量
scores := make([]int, 0, 4)
创建一个长度为0,容量为4的切片。
此时,访问score[3]将是不合法的。因为切片的长度为0,访问的下表超出了范围。
总结起来,有四种常用方法。
names := []string{"leto", "jessica", "paul"}
checks := make([]bool, 10) // 方便我们在特定位置写入数据
var names []string // 空切片,长度为0,容量为0,和append配合使用
scores := make([]int, 0, 20) // 可以制定切片的初始容量
更改切片的元素会改变其底层数组的元素内容;切片本身就是引用
func main() {
score := []int{1, 2, 3, 4, 5}
s := score[1:3]
s[0] = 999
fmt.Println(score)
}
输出: [1,999,3,4,5]
看下面两个定义:
a := make([]Saiyan, 10)
//或者
b := make([]*Saiyan, 10)
很多开发人员认为传递b
至一个函数或者让函数返回b
效率更高。然而,这里传递或者返回的都是一个切片的拷贝,这本身就是一个引用。所以就传递或者返回这个切片而言,没有什么区别。
包管理与导入
Go语言中的包和其他语言的库或模块的概念类似,目的都是为了支持模块化、封装、单独编译和代码重用。一个包的源代码保存在一个或多个以.go为文件后缀名的源文件中,通常一个包所在目录路径的后缀是包的导入路径;例如包
gopl.io/ch1/helloworld
对应的目录路径是
$GOPATH/src/gopl.io/ch1/helloworld
。
每个包都对应一个独立的名字空间。例如,在image包中的Decode函数和在unicode/utf16包中的 Decode函数是不同的。要在外部引用该函数,必须显式使用image.Decode或utf16.Decode形式访问。
当我们修改了一个源文件,我们必须重新编译该源文件对应的包(package)和所有依赖该包的其他包。
包声明
在每个Go语言源文件的开头都必须有包声明语句。包声明语句的主要目的是确定当前包被其它包导入时默认的标识符(也称为包名)。
例如,math/rand包的每个源文件的开头都包含package rand包声明语句,所以当你导入这个包,你就可以用rand.Int、rand.Float64类似的方式访问包的成员。
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println(rand.Int())
}
通常来说,默认的包名就是包导入路径名的最后一段。当需要导入两个不同路径相同名称的包时,需要为一个包重命名
包导入
接上文,当我们想导入同名的两个包时,需要为一个包重命名。
import (
"crypto/rand"
mrand "math/rand" // alternative name mrand avoids conflict
)