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语言学习之旅--基础语法的主要内容,如果未能解决你的问题,请参考以下文章

Go语言学习之旅--基础语法

go基础语法

Go语言学习之旅--初识GoLang

Go语言学习之旅--初识GoLang

Go语言学习之旅--接口

Go语言学习之旅--接口