搞定Go语言之第三天

本文介绍了Go语言中的数组、切片、Map的基本概念和操作,包括声明、初始化、遍历和一些特殊用法。此外,还详细讲解了函数的定义、参数传递、返回值以及匿名函数和闭包的概念。延迟能力`defer`的使用也在文中提及,通过示例展示了其执行顺序。文章以实例为主,帮助读者深入理解Go语言的基础数据结构和控制流程。
摘要由CSDN通过智能技术生成

数组

数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。
在这里插入图片描述

声明一维数组

语法:

var variable_name [SIZE] variable_type

实例:

var balance [10] float32

初始化一维数组

var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

balance := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

如果数组长度不确定,可以使用 … 代替数组的长度,编译器会根据元素个数自行推断数组的长度:

var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
或者
balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

一维数组遍历

a1 := [...]int{1, 3, 5, 7, 8}
for index, value := range a1 {
		other := 9 - value
		for index2 := index + 1; index2 < len(a1); index2++ {
			if a1[index2] == other {
				// 另一半在数组中,把它们的索引打印出来
				fmt.Printf("它们的索引是:(%d %d)\n", index, index2)
			}
		}
	}

完整实例:

package main

import "fmt"

// 1. 定义一个数组[1,3,5,7,8],求数组中所有元素的和
func main() {
	a1 := [...]int{1, 3, 5, 7, 8}
	fmt.Println(a1)
	// // 1. 数组求和
	// sum := 0
	// // := 相当于声明变量并且赋值
	// for _, v := range a1 {
	// 	// fmt.Println(v)
	// 	sum = sum + v
	// }
	// fmt.Println(sum)

	// 2. 找出数组中和为指定值的两个元素的下标,比如从数组[1,3,5,7,8]中找出和为8的两个元素的下标分别为(0,3)和(1,2)。
	//   遍历数组,
	// 2.1依次取出每个元素
	// 2.2 计算一下 other= 8-当前值
	// 2.3 在不在数组中,在的话把索引拿出来
	// [1, 3, 5, 7, 8]
	for index, value := range a1 {
		other := 9 - value
		for index2 := index + 1; index2 < len(a1); index2++ {
			if a1[index2] == other {
				// 另一半在数组中,把它们的索引打印出来
				fmt.Printf("它们的索引是:(%d %d)\n", index, index2)
			}
		}
	}
}

多维数组

语法:

  	var 数组名 [大小][大小]类型

比如:

var b [3][2]int

b = [3][2]int{
		[2]int{1, 2},
		[2]int{3, 4},
}

声明同时赋值:

	 var c = [3][2]int{
		{1, 2},
		{3, 4},
		{5, 6},
	 }

多维数组遍历:

 for i := 0; i < len(d); i++ {
	 	for j := 0; j < len(d[i]); j++ {
			fmt.Printf("%d-%d\n", i, d[i][j])
		}
	 }

切片

切片和数组相似,它们都是保存相同数组类型元素的容器,但是切片的元素个数是可变的, 数组不可变

切片不需要明确指定元素的个数

切片创建

1.方式一:

var s []int  //创建int类型切片
var s []string  //创建string类型切片

2.通过 make() 函数创建切片:

slice := make([]int, 5)

内部实现:

切片是一个很小的对象,它对底层的数组(内部是通过数组保存数据的)进行了抽象,并提供相关的操作方法;

切片是有三个字段的数据结构,这些数据结构包含Go语言需要操作底层数组的元数据

在这里插入图片描述

使用append可以往切片里添加元素:

var a = []int{} //空切片

a = append(a, 1)

Map

Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。

声明类型

声明map类型

	var m1 map[string]int                       //未初始化就是 nil

使用make初始化map

	m1 = make(map[string]int, 100)
	m1["nazha"] = 90
	m1["haojie"] = 100

声明map类型时直接初始化

m2 := map[string]string{
		"haojie": "hehe",
		"yawei":  "heihei",
	}

map的键值对操作

遍历键值对

for k, v := range m2 {
		fmt.Println(k, v)
	}

遍历键

for k := range m2 {
		fmt.Println(k)
	}

判断map中是否存在某个键值对

v, ok := m2["haojie"]
	// ok返回的是布尔值,能取到就返回true,取不到就返回false
	if !ok {
		fmt.Println("查无此人")
	} else {
		fmt.Println(v)
	}

删除键值对

delete(m2, "haojie")

Map和切片操作

切片的元素是map

初始化切片

mapSlice := make([]map[string]int, 3, 10)

添加元素

mapSlice = append(mapSlice, map[string]int{"aaa": 10})

mapSlice = append(mapSlice, map[string]int{"bbb": 100})

map中元素的值是切片

对外层的map做初始化

sliceMap := make(map[string][]int, 10)

对map的值(切片)做初始化

sliceMap["haojie"] = make([]int, 3, 10)
sliceMap["haojie"][0] = 1
sliceMap["haojie"][1] = 2
sliceMap["haojie"][2] = 3

函数

Go 语言函数定义格式如下:

func function_name( [parameter list] ) [return_types] {
函数体
}

函数定义解析:

  • func:函数由 func 开始声明
  • function_name:函数名称,函数名和参数列表一起构成了函数签名。
  • parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
  • return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
  • 函数体:函数定义的代码集合。

没有参数没有返回值的函数

func sayHello() {
	fmt.Println("Hello 沙河!")
}

带参数的函数

func sayHi(name string) {
	fmt.Printf("Hello %s\n", name)
}

带参数和返回值

func add(a int, b int) int {
ret := a + b
return ret
}

func add3(a, b int) (ret int) {
	ret = a + b
	return
}

可变参数

func add4(a int, b ...int) int {
	ret := a
	fmt.Println(a)
	fmt.Printf("b=%v type:%T\n", b, b)
	for _, v := range b {
		ret = ret + v
	}
	return ret
}

func add5() (int, int, int) {
	return 1, 2, 3
}

函数可以作为变量、参数、返回值

package main

import "fmt"

// 函数可以作为变量、参数、返回值

func add(a, b int) int {
	return a + b
}

func sub(a, b int) int {
	return a - b
}

// calc是一个函数,它接收三个参数,返回一个int类型的返回值
// 其中,参数a和b是int类型
// 参数f 是一个函数类型,这个函数接收两个int类型的参数,返回一个int类型的返回值
func calc(a, b int, f func(int, int) int) int {
	return f(a, b)
}

func main() {
	f1 := add
	fmt.Printf("f1:%T\n", f1)
	fmt.Println(f1(10, 20))

	//把add当成一个参数传进calc中
	ret := calc(100, 200, add)
	fmt.Println(ret)

	// 把sub当成一个参数传进calc中
	ret = calc(100, 200, sub)
	fmt.Println(ret)
}

匿名函数
匿名函数由一个不带函数名的函数声明和函数体组成,如下所示:

func(a,b int,z float64) bool{
			    return a*b
			} 
package main

import "fmt"

// 匿名函数
func main() {
	func() {
		fmt.Println("Hello world!")
	}()     //   花括号后加()表示函数调用
}

闭包函数

闭包函数,即在一个封闭作用域中的函数,这个函数可以使用封闭作用域中的所有变量。也就是使用该函数时除了函数中的变量(函数变量)还可以对闭包中的函数(自由变量进行操作)

示例一:

// 定义一个函数f1
// f1不接受参数
// f1返回一个函数类型,这个函数不接收参数也没有返回值
func f1(num int) func(int) int {

	f := func(x int) int {
		fmt.Println("找到外层函数的变量num", num)
		return num + x
	}
	return f
}

示例二:

func makeSuffixFunc(suffix string) func(string) string {
	return func(name string) string {
		if !strings.HasSuffix(name, suffix) {
			return name + suffix
		}
		return name
	}
}

示例三:

func calc(base int) (func(int) int, func(int) int) {
	add := func(i int) int {
		base += i // 引用了外层的base变量同时还修改了base
		return base
	}

	sub := func(i int) int {
		base -= i
		return base
	}
	return add, sub
}

延迟语句defer

Go语言的 defer 语句会将其后面跟随的语句进行延迟处理,在 defer 归属的函数即将返回时,将延迟处理的语句按 defer 的逆序进行执行,也就是说,先被 defer 的语句最后被执行,最后被 defer 的语句,最先被执行。

package main

import "fmt"

func testDefer() {
	defer fmt.Println(1)
	defer fmt.Println(2)
	defer fmt.Println(3)
	fmt.Println("函数马上要结束了...")
}
func main() {
	testDefer()
}

案例:

打印200~1000之间的质数(素数)

package main

import "fmt"

func main() {
	for i := 200; i < 1000; i++ {
		// fmt.Println(i)
		flag := true
		//判断i是否为质数,如果是就打印,如果不是就不打印
		for j := 2; j < i; j++ {
			if i%j == 0 {
				//不是质数
				flag = false
				break
			}
		}
		//整个第二层的for循环结束了还没有break说明是质数
		if flag {
			fmt.Printf("%d是质数.", i)
		}
	}
}

打印9*9乘法表

package main

import "fmt"
func main() {
	for i := 1; i < 10; i++ {
		for j := i; j < 10; j++ {
			fmt.Printf("%d*%d=%d\t", j, i, i*j)
		}
		fmt.Println()
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kuokay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值