Go语言实战--笔记1

打包和工具链


包


包名惯例
给包命的惯例是使用包所在目录的名字
因导入包时使用的是全路径,因此并不需要所有的名字都与别的包不同


main 包
程序编译时,会使用声明main 包的代码所在的目录的目录名作为二进制可执行文件的文件名


导入


远程导入


命名导入
导入的两个包的名字相同,可以命令一个别名代替一个包的名字,示例如下:
import (
   "fmt"
   myfmt "myfmt/fmt"
)

func mian() {
   fmt.Println("Standard Library")
   my.fmt.Println("mylib/fmt")
}

空白标识符
下划线,用来抛弃不想继续使用的值,如给导入的包赋予一个空名字,或者忽略函数返回的不感兴趣的值


函数 init


使用go工具
go build hello.go  编译hello.go文件
go clean hello.go  删除编译生成的可执行文件
示例:使用io包工作
package main
import (
   "fmt"
   "io/ioutil"
   "os"
   "github.com/goinaction/code/chapter3/words"
)
func mian() {
   filename := os.Args[1]

   contents,err := iouttil.ReadFile(filename)
   if err != nil {
      return
   }

   text := string(contents)

   context := words.CountWords(text)
   fmt.Printf("There are %d words in your text. \n",count)
}

go run hello.go       编译执行hello.go文件

go vet hello.go    检测代码的常见错误
Printf类函数调用时,类型匹配错误的参数
定义常用的方法时,方法签名的错误
错误的结构标签
没有指定字段名的结构字面量


go代码格式化
go fmt hello.go    将hello.go文件到中的代码进行格式化


go语言文档
从命令行获取文档
go doc tar     查看archive/tar包的相关资料

浏览文档
godoc -http=:6060  启动web查看文档


依赖管理
第三方依赖


数组、切片和映射
数组的内部实现和基础功能
数组是切片和映射的基础数据结构
数组是一个长度固定的数据类型,用于存储一段具有相同的类型的元素的连续块

声明和初始化
//声明一个数组,并设置为零值
//声明一个包含5个元素的整型数组
var array [5]int

//使用数组字面量声明数组
//声明一个包含5个元素的整形数组
//用具体值初始化每个元素
array := [5]int{10,20,30,40,50}

//让go自动计算声明数组的长度
//声明一个整形数组
//用具体值初始化每个元素
//容量由初始化值得数量决定
array := [...]int{10,20,30,40,50}

//声明数组并指定特定元素的值
//声明一个有5个元素的数组
//用具体值初始化索引为1和2的元素
//其余元素保持零值
array := [5]int{1:10,2:20}


使用数组
//访问数组元素
//声明一个包含5个元素的整形数组
//用具体值初始化为每一个元素
array := [5]int{10,20,30,40,50}
//修改索引为2的元素的值
array[2] = 35

//使用*运算符就可以访问元素指针所指向的值
//访问指针数组的元素
//声明包含5个元素的指向整数的数组
//用整型指针初始化索引为0和1的素组元素
array := [5]*int{0:new(int),1:new(int)}
//为索引为0和1的元素赋值
*array[0] = 10
*array[1] = 20

//把同样类型的一个数组赋值给另一个数组
//声明第一个包含5个元素的字符串数组
var array1 [5]string
//声明第二个包含5个元素的字符串数组
//用颜色初始化数组
array2 := [5]string{"Red","Blue","Green","Yellow","Pink"}
//把array2的值复制倒array1
array1 = array2

类型相同的数组
数组的长度和每个元素的类型都相同
类型不同的数组不能互相赋值

//复制数组指针,只复复制指针的值,而不会复制指针所指向的值
//把一个指针数组赋值给另一个
//声明第一个包含3个元素的指向字符串的指针数组
var array1 [3]*string
//声明第二个包含3个元素的指向字符串的指针数组
//使用字符串指针初始化这个数组
array2 := [3]*string{new(string),new(string),new(string)}
//使用颜色为每个元素赋值
*array2[0] = "Red"
*array2[1] = "Blue"
*array2[2] = "Green"
//将array2复制给array1
array1 = array2


多维数组
声明二维数组
//声明一个二维数组,两个维度分别存储4个元素和2个元素
var array [4][2]int
//使用数组字面量来声明并初始化一个二维整型数组
array := [4][2]int{
  
  {10,11},{20,21},{30,31},{40,41}}
//声明并初始化外层数组中索引为1个和3的元素
array := [4][2]int{1:{20,21},3:{40,41}}
//声明并初始化外层数组和内层数组的单个元素
array := [4][2]{1:{0:20},3:{1:41}}

//访问二维数组的元素
//声明一个2x2的二位整型数组
var array [2][2]int
//设置每个元素的整型值
array[0][0] = 10
array[0][1] = 20
array[1][0] = 30
array[1][1] = 40

//同样类型的多维数组赋值
//声明两个不同的二维整型数组
var array1 [2][2]int
var array2 [2][2]int
//为每个元素赋值
array2[0][0] = 10
array2[0][1] = 20
array2[1][0] = 30
array2[1][1] = 40
//将array2的值复制给array1
array1 = array2

//使用索引为多维数组赋值
//将array1的索引为1的维度复制到一个同类型的新数组里
var array3 [2]int = array1[1]
//将外层数组的索引为1,内层数组的索引为0的整型值复制到新的整型变量里
var value int = array1[1][0]


在函数间传递数组
//使用值传递,在函数间传递大数组
//声明一个需要8MB的数组
var array [1e6]int
//将数组传递给函数foo
foo(array)
//函数foo接受一个100万个整型值的数组
func foo(array [1e6]int) {
   ...
}

//使用指针在函数间传递大数组
//分配一个需要8MB的数组
var array [1e6]int
//将刷u在的地址传递给函数foo
foo(&array)
//函数foo接受一个指向100万个整型值得数组的指针
func foo(array *[1e6]int) {
   ...
}


切片不的内部实现和基础功能
切片是一种数据结构,该数据结构便于使用和管理数据集合
依据动态数组的概念构建,可以按需自动增长和缩小

内部实现
切片的3个字段的数据结构
指向底层数组的指针,切片访问的元素个数(即长度),切片允许增长到的元素个数(即容量)

创建和初始化
make和切片字面量
//使用长度声明一个字符串切片
//创建一个字符串切片
//其长度和容量都是5个元素
slice := make([]string,5)

//使用长度和容量声明整型切片
//创建一个整型切片
//其长度为3个元素,容量为5个元素
slice := make([]int,3,5)

//通过切片字面量来声明切片
//创建字符串切片
//其长度和容量都是5个元素
slice := []string{"Red","Blue","Green","Yellow","Pink"}
//创建一个整型切片
//其长度和容量都是3个元素
slice := []int{10,20,39}

//使用索引声明切片
//创建字符串切片
//使用空字符串初始化第100个元素
slice := []string{99:""}

//声明数组和声明切片的不同
//创建有3个元素的整型数组
array := [3]int{10,20,30}
//创建长度和容量都是3的整型切片
slice := []int{10,20,30}


nil和空切片
//创建nil切片
//创建nil整型切片
var slice []int

//声明空切片
//使用make创建空的整型切片
slice := make([]int,0)
//使用切片字面量创建空的整型切片
slice := []int{}


使用切片
赋值和切片
//使用切片字面量来声明切片
//创建一个整型切片
//其容量和长度都是5个元素
slice := []int{10,20,30,40,50}
//改变索引为1的元素的值
slice[1] = 25

//使用切片创建切片
//创建一个整型切片
//其长度和容量都是5个元素
slice := []int{10,20,30,40,50}
//创建一个新切片
//其长度为2个元素,容量为4个元素
newSlice := sice[1:3]

//如何计算长度和容量
//对底层数组容量是k的切片slice[i:j]来说
长度:j - i
容量:k - i

//修改切片内容可能导致的结果
//创建一个整型切片
slice := []int{10,20,30,40,50}
//创建一个新切片
//其长度是2个元素,容量是4个元素
newSlice := slice[1:3]
//修改newSlice索引为1的元素
//同时也修改了原来的slice的索引为2的元素
newSlice[1] = 35

//表示索引越界得语言运行时错误
//创建一个整型切片
//其长度和容量都是5个元素
slice := []int{10,20,30,40,50}
//创建一个新切片
//其长度为2个元素,容量为4个元素
newSlice := slice[1:3]
//修改newSlice索引为3得元素
//这个元素对newSlice来说并不存在
newSlice[3] = 45
//会报超出索引错误


切片增长
//使用append向切片增加元素
//创建一个整型切片
//其长度和容量都是5个元素
slice := []int{10,20,30,40,50}
//创建一个新切片
//其长度为2个元素,容量为4个元素
newSlice := slice[1:3]
//使用原有的容量来分配一新元素
//将新元素赋值为60
newSlice = append(newSlice,60)

//若切片的底层数组没有足够的可用容量,append函数会创建一个新的底层函数,
//将被引用的现有的值复制到新数字组里,再追加新的值
//使用append同时增加切片的长度和容量
//创建一个整型切片
//其长度和容量都是4个元素
slice := []int{10,20,30,40}
//向切片追加一个新元素
//将新元素复制为50
newSlice := append(slice,50)
//newSlice是一个新的数组,其容量是slice的两倍


创建切片时的3个索引
//使用切片字面量声明一个字符串切片
//创建字符串切片
//其长度和容量都是5个元素
source := []string{"Apple","Orange","Plum","Banana","Grape"}

//使用3个索引创建切片
//将第三个元素切片,并限制容量
//其长度为1个元素,容量为2个元素
slice := source[2:3:4]

//如何计算长度和容量
slice[i:j:k]
长度:j - i
容量:k - i

//强制使用append创建一个新数组,切片更改元素在新数组上进行,避免改动原数组
//设置长度和容量一样的好处
//创建字符串切片
//其长度和容量都是5个元素
source := []string{"Apple","Orange","Plum","Banana","Grape"}
//对第三个元素做切片,并限制容量
//其长度和容量都是一个元素
slice := source[2:3:3]
//向slice中追加新字符串
slice = append(slice,"Kiwi")

//使用...可以将一个切片的所有的元素追加到另一个切片里
//将一个切片追加到另一个切片
//创建两个切片,并分别用两个整数进行初始化
s1 := []int{1,2}
s2 := []int{3,4}
//将两个切片追加在一起,并显示结果
fmt.Printf("%v\n",append(s1,s2...))


迭代切片
//使用for range迭代切片
//创建一个整型切片
//其长度和容量都是4个元素
slice := []int{10,20,30,40}
//迭代每一个元素并显示其值
for index,value := range slice {
   fmt.Printf("Index: %d Value: %d\n",index,value)
}
//range会创建每个元素的副本,不是直接返回对该元素的使用

//使用空白标识符(下划线)来忽略索引值
//创建一个整型切片
//其长度和容量都是4个元素
slice := []int{10,20,30,40}
//迭代每个元素,并显示其值
for _,value := range slice {
   fmt.Printf("Value: %d\n",value)
}

//使用传统的for循环对切片进行迭代
//创建一个整型切片
//其长度和容量都是4个元素
slice := []int{10,20,30,40}
//从第三个元素开始迭代每个元素
for index := 2;index < len(slice);index ++ {
   fmt.Printf("Index: %d Value: %d\n",index,slice[index])
}


多维切片
//声明多维切片
//创建一个整型切片
slice := [][]int{
  
  {10},{100,200}}

//组合切片的切片
//创建一个整型切片的切片
slice := [][]int{
  
  {10},{100,200}}
//为第一个切片追加值为20的元素
slice[0] = append(slice[0],20)


在函数间传递切片
//在函数间传递切片
//分配包含100万个整型值得切片
slice := make([]int,1e6)
//将slice传递到函数foo
slice = foo(slice)
//函数foo接收一个整型切片,并返回这个切片
func foo(slice []int) []int {
   ...
   return slice
}


映射的内部实现和基础功能
映射是一种数据结构,用于存储一系列无序的键值对
能够基于键快速检索数据

内部实现
映射是无序集合,但可以使用类似处理数组和切片的方式迭代映射钟的元素
不能预测键值对被返回的顺序

创建和初始化
//使用make声明映射
//创建一个映射,键的类型是string,只的类型是int
dict := make(map[string]int)
//创建一个映射,键和值都是string
//使用两个键值来初始化映射
dict := map[string]string{"Red":"#da1337","Orange":"#e95a22"}

//声明一个存储字符串切片的映射
//创建你一个映射,使用字符串切片的映射
dict := map[int] []string{}


使用映射
键值对赋值给映射,是通过指定适当类型的键并给这个键赋一个值
//为映射赋值
//创建一个空映射,用来存储颜色以及颜色对应的十六进制代码
colors := map[string]string{}
//将Red的代码加入到映射
colors["Red"] = "#da1337"

//从映射获取值并判断键是否存在
//获取键Blue对应的值
value,exists := colors["Blue"]
//这个键存在吗?
if exists {
   fmt.Print(value)
}

//从映射获取值,并通过该值判断键是否存在
//获取键Blue对应的值
value := colors["Blue"]
//这个键存在吗?
if value != "" {
   fmt.Println(value)
}

//使用range迭代映射
//创建一个映射,存储颜色以及颜色对应的十六进制代码
colors := map[string]string{
   "AliceBlue":   "#f0F8ff",
   "Coral":      "#ff7F50",
   "DarkGray":       "#a9a9a9",
   "ForestGreen": "#228b22",
}
//显示映射里的所有颜色
for key,value := range colors {
   fmt.Printf("Key: %s Value: %s\n",key,value)
}

//从映射中删除一项
//删除键为Coral的键值对
delete(colors,"Coral")
//显示映射里的所有颜色
for key,value := range colors {
   fmt.Printf("Key: %s Value: %s\n",key,value)
}


在函数间传递映射
//在函数间传递映射
func main() {
   //创建一个映射,存储颜色以及颜色对应的十六进制代码
   colors := map[string]string{
   "AliceBlue":   "#f0F8ff",
   "Coral":      "#ff7F50",
   "DarkGray":       "#a9a9a9",
   "ForestGreen": "#228b22",
   }
   //显示映射里的所有颜色
   for key,value := range colors {
      fmt.Printf("Key: %s Value: %s\n",key,value)
   }
   //调用函数来移除指定的键
   removeColor(colors,"Coral")
   //显示映射里的所有颜色
   for key,value := range colors {
      fmt.Printf("Key: %s Value: %s\n",key,value)
   }
}
//removeColor 将指定的映射里的键删除
func removeColor(colors map[string]string,key string) {
   delete(colors,key)
}


go语言的类型系统
用户定义的类型
//声明一个结构类型
//user 在程序里定义一个用户类型
type user struct {
   name   string
   email  string
   ext       int
   privileged bool
}
//使用结构类型声明变量,并初始化为其零值
//声明 user类型的变量
var bill user

//使用结构字面量来声明一个结构类型的变量
//声明 user类型的变量,并初始化所有字段
//短变量声明
lisa := user{
   name:  "Lisa",
   email: "[email protected]",
   ext:   123,
   privileged:    true,
}

//使用结构字面量创建结构类型的值
//结构字面量声明
user{
   name:  "Lisa",
   "email":   "[email protected]",
   ext:   123,
   privileged:    true,
}

//不使用字段名,创建结构类型的值
//声明user类型的变量
lisa := user{"Lisa","[email protected]",123,true}

//使用其他结构类型声明字段
//admin 需要一个user类型作为管理者,并附加权限
type admin struct {
   person user
   lever string
}

//使用结构字面量来创建字段的值
//声明 admin 类型的变量
fred := admin{
   person:    user{
      name:  "Lisa",
      email: "[email protected]",
      ext:   123,
      privileged:    true,
   },
   level:"super",
}

猜你喜欢

转载自blog.csdn.net/liao__ran/article/details/114397143