文章目录

  • go语言基础笔记
  • 一、基础语法与代码风格
  • 二、编译运行
  • 三、变量与常量
  • 1、变量
  • go定义变量的四种方法:
  • 显式定义变量:
  • 短类型申明变量
  • 变量赋值
  • 交换赋值
  • 2.常量
  • go常量定义与枚举
  • 组定义方式
  • 预定义常量:true,false
  • 四.数据类型、
  • 1.基本数据类型
  • 1.1bool类型
  • 1.2整型
  • 整数运算:
  • 1.3浮点型——float32和float64
  • 1.4复数——complex64和complex128
  • 1.5 字符和字符串
  • 注意事项:
  • 2.特殊数据类型
  • 2.1 错误类型
  • 2.2 iota枚举
  • 2.3 rune类型
  • 2.4 复合数据类型
  • 五.数组
  • 1.数组定义
  • 2.数组使用
  • 六.切片
  • 1.切片基础
  • 2.创建切片
  • 2.1 基于数组——共用存储空间——同步修改数据
  • 2.2 使用内置函数make创建切片
  • 3.切片的其他内容、
  • 3.1元素遍历
  • 3.2追加数据:
  • 3.3内容复制
  • 3.4数据排序
  • 3.5字符串和切片的相关转换
  • 七.map
  • 1.概念
  • 2.创建方式
  • 2.1直接创建
  • 2.2使用make函数创建
  • 3.字典操作
  • 3.1赋值
  • 3.2访问
  • 3.3追加元素
  • 3.4删除元素
  • 3.5查找元素
  • 3.6遍历
  • 3.7字典大小
  • 3.8注意
  • 八.指针
  • 1.指针声明
  • 2.Go不支持指针的运算
  • 九.2.1.12 make、new操作
  • 1.make和new操作不同点
  • 2.new函数
  • 3.make函数
  • 4.注意
  • 4.注意


go语言基础笔记

一、基础语法与代码风格

源文件后缀名.go,入口是main()函数,main()函数必须在main包。

go语言严格区分大小写,大写公开,小写私有。

每条语句后面不需要分号,编译器会自动加上分号。(你写分号不会报错。)

每一行必须只写一句,i++必须独占一行。

强制首花括号行尾风格,不在行尾编译报错。

引入的包和定义的变量必须使用,如果不用则编译报错。

先写变量名,再写类型名。

函数允许有多个返回值。

函数本身也是一种数据类型,可以作为参数传递。

变量不赋值,默认给零值。

二、编译运行

go是跨平台的静态编译型语言,可直接编译为机器码运行,不依赖虚拟机。

go编译器在编译期间可检查出大部分问题。

go具备自动垃圾回收机制,而且加入了逃逸分析算法,提升GC效率。

go是一种强类型语言,不支持类型的自动隐式转换。

编译命令:go build main.go

运行:直接双击或命令行输入main.exe

编译+运行命令:go run main.go

三、变量与常量

1、变量

go定义变量的四种方法:

var a int 若不赋值,则默认值为0

var b int = 10 声明同时赋值

var c = 15 省略类型,可以自动推断

d :=20 这种简写不可用于定义全局变量

显式定义变量:

使用var关键字定义变量,形如: var <变量列表> 类型[=初值列表]

var v1 int   一个整型变量

var v2 string 一个字符串

var v3 [10]int 10个大小的整数数组

var v4 [ ]int 数组切片

var v5 struct 结构体 {

age  int       //结构体成员

name string    //结构体成员

}

var v6 *int 指针

var v7 map[string]int 映射

var v8 func() int 函数变量

组定义

var {
	
    a int

	b bool
)

声明并初始化

var (
	
    a, b, c int  = 10, 20, 30

	x       bool = true
)

短类型申明变量

格式:变量列表 := 值列表
v1, v2, v3 := 10, 20, 30
匿名变量:下划线是个特殊的变量名,任何赋予它的值都会被丢弃。
_, x := 100, 200

变量赋值

var v1, v2, v3 int
var v4, v5 bool
v1, v2, v3 = 10, 20, 30
v4, v5 = true, false

交换赋值

v1, v2 = v2, v1

2.常量

go常量定义与枚举

常量定义的关键字:const
输入一个空格常量必须在声明的同时赋值。
常量const关键字不能省略,所以也不能用:=。
例如:const a int = 8 定义整型常量,赋值为8
    const b ="abc"定义常量并赋值,省略类型,推断为字符串

组定义方式

const (

x int     = 10
y float64 = 20

)

预定义常量:true,false

四.数据类型、

1.基本数据类型

1.1bool类型

值是true或false,一般默认是false
布尔型不能接收其他类型的赋值,不支持自动或强制类型转换。

1.2整型

整数类型有无符号和带符号两种。GO同时支持int和uint,这两种类型的长度相同,但具体长度取决于不同编译器的实现。


GO里面也有直接定义好位数的类型:rune, int8, int16, int32, int64和byte, uint8, uint16, uint32, uint64以及特殊类型uintptr即整型指针。其中rune是int32的别称,byte是uint8的别称。

注意,一般GO的类型使用要求严格一致。例如,尽管int的长度是32位, 但int与int32并不可以互用。

整数运算:

数值运算:+,-,*,/,%,++,–

比较运算:<,>,==,<=,>=,!=

位运算:<<,>>,,&,|,&

1.3浮点型——float32和float64

浮点字面量被自动推断为float64类型。另外注意浮点数的比较一般不用==和!=进行。

1.4复数——complex64和complex128

complex128(64位实数+64位虚数),complex64(32位实数+32位虚数)。

复数定义:
var c complex64 = 5+5i

fmt.Printf(“Value is: %v, real is:%f, imag is: %f”, c, real©, imag©)

复数操作(计算复数的模、复数的三角函数值等)使用包:math/cmplx
取复数的实部和虚部分别使用real(复数)和imag(复数),用complex函数可以构造一个复数,这三个函数为系统内置函数,使用前不需要导入其他包。

1.5 字符和字符串

Go中的字符串都是采用UTF-8字符集编码。字符串是用一对双引号(“”)或反引号()括起来定义,它的类型是string。
使用单引号括起来的一个字符表示单字符;反引号用于长文本或多行文本形成的字符串。

字符串是常量,可以通过类似数组的索引访问其字节单元,但是不能修改某个字节的值;基于字符串创建的切片和原串指向相同的底层字符数组,一样不能修改!下面代码编译时会报错:
var s string = “hello”
s[0] = ‘c’ 错误,不能修改字符串中的字符
字符串和字符数组的转换:字符串可以转换为字节数组,也可以转换为Unicode的字符数组。
    {
s := “西华师范大123学abc”
    s1 := []rune(s)
    s2 := []byte(s)
    for _, a := range s1 {
        fmt.Printf(“%c “, a) 西 华 师 范 大 1 2 3 学 a b c
    }
    for _, a := range s2 {
        fmt.Printf(”%c “, a) è ¥ ¿ å å ¸ è å ¤ § 1 2 3 å ­ ¦ a b c
    }
    fmt.Println(”\n长度:”, len(s), len(s1), len(s2)) 长度: 24 12 24

注意事项:

与C和C++不一样的是,字符串末尾不包含空字符。

串连接:串连接使用+运算符。

串长度:计算长度使用函数len(字符串)。

取字符:字符常量用单引号括起来;对字符串使用方括号表示下标运算用于获取串中某位置的字符,下标从0开始。

串处理包
常用strings和strconv,前者用于基础处理,后者常用于类型转换。

串遍历
常用len函数和range关键字进行串的遍历,主要考虑英文串、中文串、混合串。

2.特殊数据类型

2.1 错误类型

GO内置error类型,用来处理错误信息,Go的package里面还专门有一个包errors来处理错误:

{
	err := errors.New("China West Normal University.")
if err != nil {
	fmt.Printn(err)
}

2.2 iota枚举

GO关键字iota用来声明enum数据(实际上常量),它默认开始值是0,每调用一次加1。

每遇到一个const,iota的值就会被重置。分组中除非被显式设置为其它值或iota,该组的第一个常量被默认设置为0,第二及后续的常量被默认设置为它前面那个常量的值,如果前面那个常量的值是iota,则它也被设置为iota。

const (					const (
b = 10 //b的值为10				b = 10   //b的值为10
c      //c为它前面那个常量值			c        //c为它前面那个常量值
d      //d=10					d = iota //d=2
e      //e=10					e        //e=iota,所以e=3
f      //f=10					f        //f=4))

2.3 rune类型

Go内置两种字符类型:一种是byte的字节类类型(byte是uint的别名〉,另一种是表示Unicode编码的字符rune。rune在Go内部是int32类型的别名,占用4个字节。Go语言默认的字符编码就是UTF-8,如果需要特殊的编码转换,可使用“unicode/utf8”标准包。

2.4 复合数据类型

Go的复合数据类型有:指针、数组、切片、字典(map)、通道(chan)、结构(struct)和接口(interface)。

五.数组

1.数组定义

var 数组名 [大小]类型
数组名 :=[大小]类型{初始化值列表}
数组名 :=[…]类型{初始化值列表}
数组名 :=[…]类型{索引号:值,……}
例子:
var arr [10]int    声明一个int类型大小为10的数组
a := [3]int{1, 2, 3}    声明一个长度为3的int数组并给每个元素赋初值
b := [10]int{1, 2, 3}    大小为10,前三个元素初值为1、2、3,其它默认为0
c := […]int{4, 5, 6}    数组大小为3
e := […]int{1:5, 6:10}     数组大小为7,下标1和6的元素值分别为5和10,其余为0
d := [2][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}}   定义多维数组
使用len(数组名)可以取数组的长度,也可以用于取某维的长度,如上例中len(d[0])。
定义数组时,给定长度必须是整型常量或整型常量表达式。

2.数组使用

数组创建完长度就固定了,不可以再追加元素。
由于长度也是数组类型的一部分,因此[3]int与[4]int是不同的类型。
数组是值类型的,数组赋值或作为函数参数都是值拷贝。
如果要使用指针需要用到后面介绍的slice类型。
可直接用循环下标使用数组元素,也可以用for…range取数组元素值。
指针数组举例:
a, b, c := 10, 20, 30
var arr [3]*int
arr[0] = &a
arr[1] = &b
arr[2] = &c

for i := 0; i < 3; i++ {
	fmt.Printf("%5d", *arr[i])
}

数组作为函数参数举例
强调:数组作为函数参数时是以传值的方式进行的,也就是在函数内部不会改变实参数组的值,这是与C语言不同的;另外,形参指定的数组大小是多少,传递的实参数组大小也只能是那么多:

func g(a [5]int) {
for v, x := range a {
fmt.Println(v, x)}}
func main() {
x := [5]int{1, 2, 3, 4, 5}
g(x)
f(x, true)
f(x, false)}

数组作为函数参数举例:
func f(a [5]int, b bool) {
for i := 0; i < len(a); i++ {
if b {
a[i] += 10
}
fmt.Printf(“%5d”, a[i])
}
fmt.Println(“”)

六.切片

1.切片基础

在很多应用场景中,数组并不能满足我们的需求。在初始定义数组时,我们并不知道需要多大的数组,因此我们就需要“动态数组”。在Go里面这种数据结构叫slice(切片)。

slice并不是真正意义上的动态数组,而是一个引用类型。slice总是指向一个底层array,slice的声明也可以像array一样,只是不需要长度。

Go为切片维护三个元素——指向底层数组的指针、切片的元素数量(len函数)和底层数组的容量(cap函数)。所以切片是一种引用类型。
例如:
var s1 [ ]int // 与声明array一样,只是少了长度
s2 := [ ]byte {‘a’, ‘b’, ‘c’, ‘d’} // 申明并初始化数据
注意slice和数组在声明时的区别:声明数组时,方括号内写明了数组的长度或使用…自动计算长度,而声明slice时,方括号内没有任何字符。

2.创建切片

创建切片

2.1 基于数组——共用存储空间——同步修改数据

格式:数组名[first:last]。省略first表示从0开始,省略last表示后面所有,实际下标范围为first到last-1。例如:
    x := [5]int{10, 20, 30, 40, 50}
    var y []int = x[:3] [10 20 30]
    z := x[2:]           [30 40 50]
    w := x[2:4]         [30 40]

2.2 使用内置函数make创建切片

注意: 由make 创建的切片各元素被默认初始化为切片元素类型的零值
格式:make(类型, 长度, 容量)
s := make([ ]int, 5) }   元素个数为5的切片
t := make([ ]string, 5, 10) }   元素个数为5,容量为10的切片
u := [ ]int{1, 2, 3} }   含有三个元素的切片
var v [ ]int }   空切片,v为空指针,这种定义无意义
w := [ ]int{} }   没有元素的切片,w不是空指针

3.切片的其他内容、

3.1元素遍历

如前面的例子,使用for ?, ? := range 切片{……}语句可以很方便地对切片进行遍历。
元素追加

3.2追加数据:

切片 = append(切片, 数据)
将另一个切片的所有数据追加到第一个切片的后面使用“切片名…”作数据参数。
slice的默认开始位置是0,s[:n]等价于s[0:n]
如果从一个数组里面直接获取slice,可以这样ar[:],因为默认第一个序列是0,第二个是数组的长度,即等价于ar[0:len(ar)]

3.3内容复制

copy(切片1, 切片2)

3.4数据排序

可以利用sort包直接对常规类型切片元素排序,如sort.Ints(a)//a是int型切片

3.5字符串和切片的相关转换

str := hello,优秀的同学位!  通过字符串字面量初始化一个字符串str
a := [ ]byte(str)        将字符串转换为[ ]byte 类型切片
b := [ ]rune(str)        将字符串转换为[ ]rune 类型切片

七.map

1.概念

map也就是Python中字典的概念,它的格式为:map[索引类型]值类型

map的读取和设置类似于slice,通过索引来操作,不过slice的索引只能是int类型,而map多了很多类型,可以是int、string及所有完全定义了==与!=操作的类型(即可比较的类型)

2.创建方式

2.1直接创建

var dict map[string]int    与切片一样,只定义字典是无意义的,是空指针

var dict map[string]int = map[string]int{}   空字典,即没有元素的字典

dict := map[string]int{“abc”: 12, “bcd”: 100, “chen”: 200}   定义并赋值

for x, y := range dict {
    fmt.Println(x, y)
}

2.2使用make函数创建

dict := make(map[string]int, 大小)
这里大小可以给0,后面直接使用赋值的方式添加元素即可

3.字典操作

3.1赋值

字典[索引键值]=值

3.2访问

变量=字典[索引键值]

3.3追加元素

字典[索引键]=值

3.4删除元素

delete(字典, 索引键值)

3.5查找元素

if 值变量, ok := 字典变量[索引键值]; ok{

}

3.6遍历

可以使用“for 索引变量, 值变量 := range 字典”的方式进行

3.7字典大小

使用len(字典)取得。

3.8注意

字典是无序的,若要按索引或值排序,可以通过遍历的方式将索引或值单独生成切片,再用sort包直接对切片进行排序。

八.指针

1.指针声明

Go语言支持指针,指针的声明类型为“*T”,Go同样支持多级指针**T。通过在变量名前加&来获取变量的地址。
在赋值语句中,*T出现在等号左边表示指针声明,*T出现在等号右边表示取指针指向的值。例如:

var p *int
var a = 10
p = &a
q := *p

2.Go不支持指针的运算

函数中允许返回局部变量的地址,Go编译器会自动将这种局部变量的空间分配在堆上。例如:
func sum(a, b int) *int{
sum := a + b
return &sum

九.2.1.12 make、new操作

1.make和new操作不同点

1.make用于内建类型(map、slice 和channel)的内存分配。new用于各种类型的内存分配。

2.new函数

内建函数new本质上说跟其它语言中的同名函数功能一样:new(T)分配了零值填充的T类型的内存空间,并且返回其地址,即一个*T类型的值。用GO的术语说,它返回了一个指针,指向新分配的类型T的零值空间。有一点非常重要:new返回指针。

3.make函数

内建函数make(T, args)与new(T)有着不同的功能,make只能创建slice、map和channel,并且返回一个有初始值(非零)的T类型,而不是*T。本质来讲,导致这三个类型有所不同的原因是指向数据结构的引用在使用前必须被初始化。例如,一个slice,是一个包含指向数据(数组)的指针、长度和容量的三项描述符;这些项目被初始化之前,slice为nil。对于slice、map和channel来说,make初始化了内部的数据结构,填充适当的值。

4.注意

1.make返回初始化后的(非零)值。
2.关于“零值” 并非是空值,而是一种“变量未填充前”的默认值,通常为0。部分类型的“零值”如下:
int 0    int8 0
int32 0    int64 0
uint 0x0    rune 0   //rune的实际类型是 int32
byte 0x0   // byte的实际类型是uint8   float32 0 //长度为 4 byte
float64 0   //长度为 8 byte    bool   false
string “”
了内部的数据结构,填充适当的值。

4.注意

1.make返回初始化后的(非零)值。
2.关于“零值” 并非是空值,而是一种“变量未填充前”的默认值,通常为0。部分类型的“零值”如下:
int 0    int8 0
int32 0    int64 0
uint 0x0    rune 0   //rune的实际类型是 int32
byte 0x0   // byte的实际类型是uint8   float32 0 //长度为 4 byte
float64 0   //长度为 8 byte    bool   false
string “”