【go语言 | 第2篇】Go变量声明 + 常用数据类型的使用

文章目录

  • 变量声明方式
  • [常量 const 与 iota](#常量 const 与 iota)
  • 函数的多返回值
  • [init 函数和 import 导包](#init 函数和 import 导包)
    • [import 匿名和别名导包](#import 匿名和别名导包)
  • 指针
  • [defer 语句调用顺序](#defer 语句调用顺序)
  • 数组与动态数组
    • [1. 数组](#1. 数组)
    • [2. 动态数组(切片)](#2. 动态数组(切片))
    • [3. slice 切片的声明方式](#3. slice 切片的声明方式)
    • [4. 切片的追加与截取](#4. 切片的追加与截取)
  • map
    • [1. map 声明方式](#1. map 声明方式)
    • [2. map 的常用方法](#2. map 的常用方法)
  • [struct 的使用](#struct 的使用)

变量声明方式

go 复制代码
package main

import "fmt"

// 全局变量
var aa = "hello"
var bb string = "hello"
// 错误声明方式
// cc := "hello"

func main() {
	// 方法一:创建一个变量,赋默认值
	var a int
	fmt.Println(a)

	// 方法二:创建一个变量,并赋值
	var b int = 10
	fmt.Println(b)

	var c int = 100
	fmt.Println(c)
	fmt.Printf("type of c %T\n", c)

	// 方法三:初始化时,省去数据类型,通过赋值自动匹配类型
	var d = 100
	fmt.Println(c)
	fmt.Printf("type of d %T\n", d)

	var e = "hello"
	fmt.Println(e)
	fmt.Printf("type of e %T\n", e)	

	// 方法四: (常用)省去 var 关键字,直接自动匹配
	f := 100
	fmt.Println(f)
	fmt.Printf("type of f %T\n", f)

	g := "hello"
	fmt.Println(g)
	fmt.Printf("type of g %T\n", g)

	h := 1.25
	fmt.Println(h)
	fmt.Printf("type of h %T\n", h)

	fmt.Println("================================================")
	// 全局变量
	fmt.Println("aa = ", aa , "  bb = ", bb)

	fmt.Println("================================================")
	// 声明多个变量
	var i, j int = 10, 20
	fmt.Println("i = ", i, "  j = ", j)

	var s, t = 100, "world"
	fmt.Println("s = ", s, "  t = ", t)
	// (常用)多行多变量声明
	var (
		x int = 88
		flag bool = true
	)
	fmt.Println("x = ", x, "  flag = ", flag)

}
  1. 局部变量声明:
    (1)自动赋默认值:var a int
    (2)初始化赋值:var b int = 100
    (3)省去数据类型,自动匹配数据类型:var c = "hello"
    (4)省去 var 关键字:d := 100
  2. 全局变量声明:不支持方法四(不支持省去 var 关键字的写法)
  3. 多变量声明:
    (1)单行声明:var i, j int = 10, 20var k t = 100, "hello"
    (2)多行声明:
go 复制代码
var (
		x int = 88
		flag bool = true
	)

常量 const 与 iota

go 复制代码
package main

import "fmt"

// const用于枚举
const (
	BEIJING = 0
	SHANGHAI = 1
	CHENGDU = 2
)

const (
	SHENGZHENG = iota  // 0
	CHONGQING = iota  // 1
	XIANGGANG = iota // 2
)

const (
	a, b = iota, iota + 1       // iota = 0, a = 0, b = 1
	c, d = iota + 1, iota + 2   // iota = 1, c = 2, d = 3
	e, f = iota + 2, iota + 3   // iota = 2, e = 4, f = 5

	g, h = iota * 2, iota * 3   // iota = 3, g = 6, h = 9
	i, j = iota * 3, iota * 4   // iota = 4, i = 12, j = 16
)

func main() {
	// 常量
	const x int = 10
	fmt.Println("x = ", x)
	
	// x = 100   报错,常量不能被修改

	fmt.Println("================================================")
	// 枚举值
	fmt.Println("BEIJING = ", BEIJING)
	fmt.Println("SHANGHAI = ", SHANGHAI)
	fmt.Println("CHENGDU = ", CHENGDU)

	fmt.Println("================================================")
	// iota 枚举值
	fmt.Println("SHENGZHENG = ", SHENGZHENG)
	fmt.Println("CHONGQING = ", CHONGQING)
	fmt.Println("XIANGGANG = ", XIANGGANG)

	fmt.Println("================================================")
	fmt.Println("a = ", a, "  b = ", b)
	fmt.Println("c = ", c, "  d = ", d)
	fmt.Println("e = ", e, "  f = ", f)
	fmt.Println("g = ", g, "  h = ", h)
	fmt.Println("i = ", i, "  j = ", j)

	// iota 只能用在const中进行累加效果,配合 const 使用
	// var t int = iota

}

注意:const 通常用于枚举,iota 是与 const 配合使用表示枚举类型。

函数的多返回值

go 复制代码
package main

import "fmt"

// 写法一:多个返回值,匿名返回值
func foo1(a string, b int) (int, int) {
	fmt.Println("foo1=======================================")
	fmt.Println("a = ", a, "  b = ", b)

	return 100, 200
}

// 写法二:多个返回值,命名返回值
func foo2(a string, b int) (x int, y int) {
	fmt.Println("foo2=======================================")
	fmt.Println("a = ", a, "  b = ", b)

	x = 1000
	y = 2000

	return 
}

// 写法三:多个返回值数据类型相同,省略多余的返回值类型
func foo3(a string, b int) (x, y int) {
	fmt.Println("foo3=======================================")
	fmt.Println("a = ", a, "  b = ", b)

	x = 88
	y = 99
	
	return 
}

func main() {
	c, d := foo1("foo1", 100)
	fmt.Println("c = ", c, "  d = ", d)

	e, f := foo2("foo2", 200)
	fmt.Println("e = ", e, "  f = ", f)

	g, h := foo3("foo3", 300)
	fmt.Println("g = ", g, "  h = ", h)
}

init 函数和 import 导包

import 匿名和别名导包

go 复制代码
import (
	_ "GoLearn/5-init/lib1" // 匿名导包
	// mylib2 "GoLearn/5-init/lib2" // 别名导包
	. "GoLearn/5-init/lib2"
)
func main() {
	//lib1.Lib1Test()
	//lib2.Lib2Test()

	//mylib2.Lib2Test()
	Lib2Test()
}
  1. 匿名导包:_ lib1 给 lib1 包起一个别名,匿名,无法使用 lib1 包的方法,但是可以执行 lib1 内部的 init 方法。
  2. 别名导包:mylib2 lib2 给 lib2 包起一个别名 mylib2,使用 mylib2.func() 调用 lib2 包的方法。
  3. . lib2 将 lib2 包中的方法全部导入到当前本包的全部作用中,直接调用方法执行(不建议,可能与本包内的方法冲突)。

指针

go 复制代码
package main

import "fmt"

func swap(a *int, b *int) {
	var temp = *a
	*a = *b
	*b = temp
}

func main() {
	var a int = 10
	var b int = 20

	// 交换 a 和 b
	swap(&a, &b)

	fmt.Println("a = ", a, "  b = ", b)
}

defer 语句调用顺序

go 复制代码
package main

import "fmt"

func foo1() {
	fmt.Println("A")
}

func foo2() {
	fmt.Println("B")
}

func foo3() {
	fmt.Println("C")
}

func main() {
	defer foo1()
	defer foo2()
	defer foo3()
}

defer 执行顺序:通过栈的方式,依次压入栈,再依次出栈执行

注意:defer 和 return 哪个先执行,哪个后执行?

go 复制代码
package main

import "fmt"

func deferFoo() int {
	fmt.Println("deferFoo()")
	return 0
}

func returnFoo() int {
	fmt.Println("returnFoo()")
	return 0
}

func deferAndReturn() int {
	defer deferFoo()

	return returnFoo()
}
func main() {
	deferAndReturn()
}


return 在 defer 前先执行。defer 出栈是在方法的 } 后,也就是方法已经完全结束后,才出栈执行。

数组与动态数组

1. 数组

go 复制代码
package main

import "fmt"

// 固定长度数组在传参时,严格匹配数组类型
func foo(myArray [3]int) {
	for _, value := range myArray {
		fmt.Println(value)
	}

	myArray[0] = 11
}

func main() {
	// 固定长度的数组
	var myArray1 [10]int
	myArray2 := [10]int{1, 2, 3, 4}
	myArray3 := [3]int{88, 99, 100}

	// 遍历数组方式一
	for i := 0; i < len(myArray1); i++ {
		fmt.Println(myArray1[i])
	}
	// 遍历数组方式二
	for index, value := range myArray2 {
		fmt.Println("index = ", index, "  value = ", value)
	}



	// 查看数组类型
	fmt.Printf("myArray1 types = %T\n", myArray1)
	fmt.Printf("myArray2 types = %T\n", myArray2)
	fmt.Printf("myArray3 types = %T\n", myArray3)


	foo(myArray3)
	fmt.Println("===========================================")
	for _, value := range myArray3 {
		fmt.Println(value)
	}
}

可以发现,固定长度的数组在传参时,是值传递

2. 动态数组(切片)

go 复制代码
package main

import "fmt"

func foo(myArray []int) {
	// 引用传递
	for _, value := range myArray {
		fmt.Println(value)
	}

	myArray[0] = 100
}

func main() {
	myArray := []int{1, 2, 3, 4, 5} // 动态数组, 切片 slice

	fmt.Printf("myArray type = %T\n", myArray)

	foo(myArray)
	fmt.Println("===========================================")
	for _, value := range myArray {
		fmt.Println(value)
	}
}

动态数组传参上是引用传递,不同元素长度的动态数组的形参一致。

3. slice 切片的声明方式

go 复制代码
package main

import "fmt"

// 声明切片 slice 的方式
func main() {
	// 方式一:声明 slice1 是一个切片,并赋初始值为 1, 2, 3, 长度为3
	slice1 := []int{1, 2, 3}

	// 方式二:声明 slice2 是一个切片,但并没有给 slice2 分配空间
	var slice2 []int
	//slice2 = make([]int, 3)  // 分配3的内存,初始化值为 0 
	//slice2[0] = 100

	// 方式三:声明 slice3 是一个切片,分配3个内存,初始化值为 0
	var slice3 = make([]int, 3)

	// 方式四:声明 slice4 是一个切片,分配3个内存,初始化值为 0,通过 := 推导出 slice4 是一个切片
	slice4 := make([]int, 3)


	fmt.Printf("len = %d  slice1 = %v\n", len(slice1), slice1)
	fmt.Printf("len = %d  slice2 = %v\n", len(slice2), slice2)
	fmt.Printf("len = %d  slice3 = %v\n", len(slice3), slice3)
	fmt.Printf("len = %d  slice4 = %v\n", len(slice4), slice4)

	// 判断 slice 是否为空
	if slice2 == nil {
		fmt.Println("slice is nil")
	} else {
		fmt.Println("slice is not nil")
	}
}

4. 切片的追加与截取

切片的追加:

go 复制代码
package main

import "fmt"

func main() {
	// 创建一个长度为3,容量为5的切片,默认值为[0, 0, 0]
	var slice1 = make([]int, 3, 5)
	fmt.Printf("len = %d, cap = %d, slice1 = %v\n", len(slice1), cap(slice1), slice1)

	// 向切片中追加一个元素 1 
	slice1 = append(slice1, 1)
	fmt.Printf("len = %d, cap = %d, slice1 = %v\n", len(slice1), cap(slice1), slice1)

	// 向切片中追加一个元素 2
	slice1 = append(slice1, 2)
	fmt.Printf("len = %d, cap = %d, slice1 = %v\n", len(slice1), cap(slice1), slice1)

	// 此时容量已满,再次向切片中追加元素 3,容量会自动扩容为原来的2倍
	slice1 = append(slice1, 3)
	fmt.Printf("len = %d, cap = %d, slice1 = %v\n", len(slice1), cap(slice1), slice1)
}

切片的截取和拷贝:

go 复制代码
package main

import "fmt"

func main() {
	slice1 := []int{1, 2, 3}
	fmt.Printf("len = %d, cap = %d, slice1 = %v\n", len(slice1), cap(slice1), slice1)

	// 截取 slice1 的第0个元素到第1个元素,作为 slice2 的引用
	slice2 := slice1[0:2]
	fmt.Printf("len = %d, cap = %d, slice2 = %v\n", len(slice2), cap(slice2), slice2)
	// 修改 slice2 的值,slice1 的值会改变,因为是引用传递,指向的同一个位置
	slice2[0] = 100
	fmt.Printf("len = %d, cap = %d, slice1 = %v\n", len(slice1), cap(slice1), slice1)
	fmt.Printf("len = %d, cap = %d, slice2 = %v\n", len(slice2), cap(slice2), slice2)

	
	// copy 将底层数组的值拷贝到新的数组中
	slice3 := make([]int, 3)
	// 将 slice1 的值拷贝到 slice3
	copy(slice3, slice1)
	fmt.Printf("len = %d, cap = %d, slice3 = %v\n", len(slice3), cap(slice3), slice3)
	
}

map

1. map 声明方式

java 复制代码
package main

import "fmt"

// map 声明方式
func main() {
	// ======> 方式一:声明 map1 是一个 map 类型,key 为 string,value 为 string
	var map1 map[string]string
	if (map1 == nil) {
		fmt.Println("map1 是一个空 map")
	}
	// 使用 map 前,为其分配空间
	map1 = make(map[string]string, 10)
	map1["one"] = "111"
	map1["two"] = "222"
	map1["three"] = "333"
	fmt.Println(map1)
	fmt.Println("=======================================================")


	// ======> 方式二:
	map2 := make(map[string]string)
	map2["one"] = "111"
	map2["two"] = "222"
	map2["three"] = "333"
	fmt.Println(map2)
	fmt.Println("=======================================================")

	// ======> 方式三:
	map3 := map[int]string {
		1: "one",
		2: "two",
		3: "three",
	}
	fmt.Println(map3)
	fmt.Println("=======================================================")
}

2. map 的常用方法

java 复制代码
package main

import "fmt"

func printCity(cityMap map[string]string) {
	for key, value := range cityMap { 
		fmt.Println(key, ":", value)
	}
}

func addCity(cityMap map[string]string, key string, value string) {
	cityMap[key] = value
}

func main() { 
	cityMap := make(map[string]string)

	// 添加元素
	cityMap["China"] = "北京"
	cityMap["Japan"] = "东京"
	cityMap["USA"] = "华盛顿"

	// 遍历
	// for key, value := range cityMap { 
	// 	fmt.Println(key, ":", value)
	// }
	printCity(cityMap)

	// 修改
	cityMap["China"] = "上海"
	fmt.Println(cityMap)

	// 删除
	delete(cityMap, "China")
	fmt.Println(cityMap)

	fmt.Println("=======================================================")

	addCity(cityMap, "China", "成都") // map 是引用传递
	fmt.Println(cityMap)
}

struct 的使用

java 复制代码
package main

import "fmt"


type Book struct {
	title string
	author string
}

func changeBook(book Book) {
	// 传递 book 的副本
	book.title = "Go 语言教程"
}

func changeBook2(book *Book) {
	// 传递指针
	book.title = "Go 语言教程"
}
func main() {
	var book1 Book
	book1.title = "Go 语言"
	book1.author = "Go 语言中文网"

	fmt.Printf("%v\n", book1)

	changeBook(book1)
	fmt.Printf("%v\n", book1)

	changeBook2(&book1)
	fmt.Printf("%v\n", book1)

}
相关推荐
报错小能手3 小时前
STL_unordered_map
开发语言·c++·哈希算法
疯狂的程序猴3 小时前
App Store上架完整流程与注意事项详解
后端
开心就好20253 小时前
把 H5 应用上架 App Store,并不是套个壳这么简单
后端
CreasyChan3 小时前
C#特性(Attributes)详解
开发语言·c#
历程里程碑3 小时前
C++ 9 stack_queue:数据结构的核心奥秘
java·开发语言·数据结构·c++·windows·笔记·算法
tirelyl3 小时前
LangChain.js 1.0 + NestJS 入门 Demo
后端
csbysj20203 小时前
JavaScript AI 编程助手
开发语言
王中阳Go背后的男人3 小时前
GoFrame vs Laravel:从ORM到CLI工具的全面对比与迁移指南
后端·go
t198751283 小时前
基于MATLAB的线性判别分析(LDA)降维算法实现方案
开发语言·算法·matlab