Go语言学习之旅--基础语法
Posted 赵jc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言学习之旅--基础语法相关的知识,希望对你有一定的参考价值。
变量
变量有三种声明方式
- 第一种:var 变量名 类型 = 值
var i int = 10
- 第二种: var 变量名 = 值
var j = 10
- 第三种: 变量名 := 值,自动推导类型
name := "zjc"
一些特殊的情况:一次声明多个变量,变量名和值一一对应
var a, sex, b = 1, "man", 7
也可以这样
a, sex, b := 2, "man", 4
函数外声明全局变量
var (
n1 = 1
n2 = 2
n3 = 3
)
var n4 = "n4"
func main()
fmt.Println("n1 = ", n1, ", n2 = ", n2, "n3 = ", n3, ", n4 = ", n4)
Go和其他语言不一样的一点便是:变量声明后必须使用。
常量
- 常量必须赋初值,而且不可更改
- 常量只能修饰布尔、数值、字符串类型
const a int = 1
const name = "zjc"
const b = 4 / 2
iota
- iota比较特殊,可以被认为一个可以被编辑器修改的常量,他的默认值是0,每一次调用加1,遇到const挂念自时被重置为0。
const (
a = iota
b = iota
c = iota
)
fmt.Println(a, b, c) // 0 1 2
也可以使用_跳过某些值
const (
a1 = iota //0
_ //1
a2 = iota //2
)
数据类型
基本数据类型与复杂数据类型
基本数据类型:
- 数值型:
1、整数类型(int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64、byte)
2、浮点类型(float32、float64)
3、复数(complex64、complex128)
- 字符型:没有专门的字符型,使用byte保存单个字母字符
- 布尔型、字符串
复杂数据类型:
指针、数组、结构体、管道、函数、切片、接口、映射
值类型与引用类型
值类型:基本数据类型、数组、结构体。变量直接存储值,通常存储于栈中,函数传参时使用值传递
引用类型:指针、切片、映射、管道、接口等。变量存储的是值的地址,通常存储于堆中,会发生GC,函数传参时使用引用传递。
查看变量类型
查看变量类型:%T
a, sex:= 2, "man"
fmt.Printf("a的类型:%T,sex的类型:%T\\n", a, sex)
查看变量占用内存大小时,先导入unsafe和fmt包,再调用unsafe.Sizeof函数就行
import (
"fmt"
"unsafe"
)
fmt.Printf("a占用内存大小:%d, sex占用内存大小:%d", unsafe.Sizeof(a), unsafe.Sizeof(sex))
数组
数组是相同数据类型的一组数据的集合,数组一旦定义长度不能修改
,数组可以通过下标来访问元素。
- 数组的定义
var a1 [2]int
var a2 [3]string
fmt.Printf("a1: %T\\n", a1)
fmt.Printf("a1: %v\\n", a1)
fmt.Printf("a2: %T\\n", a2)
fmt.Printf("a2: %v\\n", a2)
- 数组的初始化
var a1 = [3]int1,2
fmt.Printf("a1: %v\\n", a1)
var a2 = [2]string"hello", "world"
fmt.Printf("a2: %v\\n", a2)
- 指定索引的值来进行初始化
var a = [...]int0 : 1, 2 : 2
var s = [...]string1 : "tom", 2 :"zjc"
fmt.Println(a)
fmt.Println(s)
- 省略数组的长度…
var a1 = [...]int1,2,3
fmt.Printf("len(a1): %v\\n", len(a1))
fmt.Printf("a1: %v\\n", a1)
切片
数组是固定长度,可以容纳相同数据类型的元素的集合。当长度固定时,使用还是带来一些限制,比如:我们申请的长度太大浪费内存,太小又不够用。鉴于上述原因,有了go语言的切片,可以把切片理解为,可变长度的数组
,其实它底层就是使用数组实现的,增加了自动扩容功能。切片(Slice)是一个拥有相同类型元素的可变长度的序列。
- 基础语法
声明一个切片和声明一个数组类似,只要不添加长度就可以了
var 名称 []类型
切片是引用类型,可以使用make函数来创建切片,len为数组的长度,也为切片的起始长度
var slice1 [] 类型 = make([]type, len)
也可以简写为
slice1 := make([]类型,len)
也可以指定容量,其中capacity为可选参数
make([]类型,len,capacity)
- 切片的声明
第一种:var 名称 []类型 并未分配内存
var s1 []int
var s2 []string
第二种:make形式,分配内存
var s3 = make([]int, 2)
- 切片的长度和容量
切片拥有自己的长度和容量,我们可以通过使用内置的len()函数求长度,使用内置的cap()函数求切片的容量
var names = []string"tom", "zjc"
var numbers = []int1,2,3
fmt.Printf("len(names): %v\\n", len(names))
fmt.Printf("cap(names): %v\\n", cap(numbers))
fmt.Printf("len(names): %v\\n", len(names))
fmt.Printf("cap(names): %v\\n", cap(numbers))
var s1 = make([]string, 2, 3)
fmt.Printf("s1: %v\\n", s1)
fmt.Printf("len(names): %v\\n", len(s1))
fmt.Printf("cap(names): %v\\n", cap(s1))
切片的增删和copy
- 添加
s1 := []int
s1 = append(s1, 1)
s1 = append(s1, 2)
s1 = append(s1, 3, 4, 5, 6)//添加多个元素
fmt.Printf("s1: %v\\n", s1)
s3 := []int3,4,5
s4 := []int1,2
s4 = append(s4, s3...)//添加另一个切片
fmt.Printf("s4: %v\\n", s4)
- 删除
- 公式:要将切片a中删除索引为index的元素,操作方法是a = append(a[:index],a[index + 1 :0…)
s1 := []int1,2,3,4,5
fmt.Printf("s1: %v\\n", s1)
//删除索引为2的元素
s1 = append(s1[:2], s1[3:]...)
fmt.Printf("s1: %v\\n", s1)
- 切片的copy(深拷贝)
s1 := []int1,2,3
s2 := s1
s1[0] = 100
fmt.Printf("s1: %v\\n", s1)
fmt.Printf("s2: %v\\n", s2)
s3 := make([]int, 3)
copy(s3, s1)
s1[0] = 1
fmt.Printf("s1: %v\\n", s1)
fmt.Printf("s2: %v\\n", s3)
字符串
- 一个Go语言字符串是一个任意“字节的常量序列。
go语言字符串字面量
在Go语言中,字符串字面量使用双引号““
或者反引号`
来创建。双引号用来创建可解析的字符串,支持转义,但不能用来引用多行;反引号用来创建原生的字符串字面量,可能由多行组成,但不支持转义,并且可以包含除了反引号外其他所有字符。双引号创建可解析的字符串应用最广泛,反引号用来创建原生的字符串则多用于书写多行消息,html以及正则表达式。
- 字符串的定义
func main()
var s1 string = "hello1"
var s2 = "hello2"
s3 := "hello3"
fmt.Printf("s1: %v\\n", s1)
fmt.Printf("s2: %v\\n", s2)
fmt.Printf("s3: %v\\n", s3)
s4 := `
line 1
line 2
line 3
`
fmt.Printf("s4: %v\\n", s4)
- 字符串的拼接
s1 :="tom"
s2 := "20"
msg := s1 + s2
fmt.Printf("msg: %v\\n", msg)
- 字符串的切片
str := "hello world"
n := 3
m := 5
fmt.Println(str[n]) //获取字符串索引位置为n的原始字节
fmt.Println(str[n:])//截取字符串索引位置为n到m-1的字符串
fmt.Println(str[n:])//截取字符串索引位置为n到len(s)-1的字符串
fmt.Println(str[:m])//截取字符串索引位置为0到m-1的字符串
类型转换
不同数据类型之间必须显式类型转换
a1 := 1.2
a2 := int(a1)
fmt.Println("a2 = ", a2)
如果范围大转换成范围小的,可能会发生精度损失,以下是例子:
var i1 int32 = 12
var i2 int8
var i3 int8
i2 = int8(i1) + 127 // 运行时溢出,得不到想要结果
i3 = int(i1) + 128 // 直接溢出,编译错误
fmt.Println("i2 = ", i2)
基本数据类型转string:
n1 := 10
var s0 = fmt.Sprintf("%d", n1)
fmt.Printf("s type:%T, s = %v\\n", s0, s0)
b := true
s0 = fmt.Sprintf("%t", b)
fmt.Printf("s type:%T, s = %v\\n", s0, s0)
也可以用strconv包中的函数进行转换,用之前先导入strconv包,然后调用函数进行转换。
n1 := 10
s0 := strconv.FormatInt(int64(n1), 10) // 10表示十进制
fmt.Printf("s type:%T, s = %v\\n", s0, s0)
a1 := 20.0
s0 = strconv.FormatFloat(a1, 'f', 10, 64) // 'f'表示浮点数类型、10表示精度10位,64表示float64
fmt.Printf("s type:%T, s = %v\\n", s0, s0)
指针
Go语言中的指针操作非常简单,只需要记住两个符号:8(取地址)和*(根据地址取值)。
指针地址和指针类型
- 每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用&字符放在变量前面对变量进行取地址操作。Go语言中的值类型(int、float、boo1、string、array、struct)都有对应的指针类型,如:*int、*int64、*string等。
示例
var ip *int
fmt.Printf("ip: %v\\n", ip)//nil
fmt.Printf("ip: %T\\n", ip)
var i int = 100
ip = &i
fmt.Printf("ip: %v\\n", ip)
fmt.Printf("ip: %T\\n", ip)
指针数组
Go语言中的指针指向数组之后并不像C语言那样指向数组的首元素,而是指向数组中的每一个元素
- 定义语法
var ptr [size]int
- 举例
a := [3]int1,2,3
var ptr [3]*int
for i := 0; i < len(a); i++
ptr[i] = &a[i]
fmt.Printf("ptr: %v\\n", ptr)
for i := 0; i < len(a); i++
fmt.Printf("ptr: %v\\n", *ptr[i])
for-range遍历
这是一种同时获取索引和值或键值的遍历方式
func main()
s := "zjc123"
for index, value := range s
fmt.Printf("%d---%c\\n", index, value)
以上是关于Go语言学习之旅--基础语法的主要内容,如果未能解决你的问题,请参考以下文章