20220712go语言基础知识

歆瑶的小房子 歆瑶的小房子     2022-11-29     229

关键词:

基础

1. 内置函数
2. 流程控制
2.1. if与switch
2.1.1. if
2.1.2. switch
2.2. for
3. 指针
3.1. 指针地址和指针类型
3.2. 指针取值
3.3. 空指针
4. 数组Array
4.1. 数组定义
4.2. 数组定义
4.3. 与数组相关的函数
5. 切分Slice
5.1. 切分Slice定义
5.2. 切分Slice初始化
5.3. cap与len
5.4. 操作方法
5.4.1. append 元素的添加与删除
5.4.2. copy 切片拷贝
5.4.3. slice遍历
5.5. 其他操作
5.6. 超出原 slice.cap 限制,就会重新分配底层数组,即便原数组并未填满
6. map
6.1. 定义 Map
6.2. map基本使用
6.3. 判断某个键是否存在
6.4. 遍历
6.5. delete()函数删除键值对
6.6. 与切片擦出火花
7. 内置函数

1. 内置函数


append -- 用来追加元素到数组、slice中,返回修改后的数组、slice
close -- 主要用来关闭channel
delete -- 从map中删除key对应的value
panic -- 停止常规的goroutine (panic和recover:用来做错误处理)
recover -- 允许程序定义goroutine的panic动作
real -- 返回complex的实部 (complex、real imag:用于创建和操作复数)
imag -- 返回complex的虚部
make -- 用来分配内存,返回Type本身(只能应用于slice, map, channel)
new -- 用来分配内存,主要用来分配值类型,比如int、struct。返回指向Type的指针
cap -- capacity是容量的意思,用于返回某个类型的最大容量(只能用于切片和 map)
copy -- 用于复制和连接slice,返回复制的数目
len -- 来求长度,比如string、array、slice、map、channel ,返回长度
print、println -- 底层打印函数,在部署环境中建议使用 fmt

2. 流程控制

2.1. if与switch

2.1.1. if

go和PHP相比,实际上没有特别的区别只是语法上需要注意一下语法即可

• 可省略条件表达式括号。

• 持初始化语句,可定义代码块局部变量。

• 代码块左 括号必须在条件表达式尾部。

if 布尔表达式 
/* 在布尔表达式为 true 时执行 */

示例

if n := "abc"; x > 0  // 初始化语句未必就是定义变量, 如 println("init") 也是可以的。
println(n[2])
else if x < 0 // 注意 else if 和 else 左大括号位置。
println(n[1])
else
println(n[0])

*不支持三元操作符(三目运算符) "a > b ? a : b"。

2.1.2. switch

switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上直下逐一测试,直到匹配为止。 Golang switch 分支表达式可以是任意类型,不限于常量。可省略 break,默认自动终止。

switch var1 

case val1:
...
case val2:
...
default:
...

变量 var1 可以是任何类型,而 val1 和 val2 则可以是同类型的任意值。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式。 您可以同时测试多个可能符合条件的值,使用逗号分割它

们,例如:case val1, val2, val3。

/* 定义局部变量 */

var grade string = "B"
var marks int = 90
switch marks
case 90: grade = "A"
case 80: grade = "B"
case 50,60,70 : grade = "C"
default: grade = "D"

switch
case grade == "A" :
fmt.Printf("优秀!\\n" )
case grade == "B", grade == "C" :
fmt.Printf("良好\\n" )
case grade == "D" :
fmt.Printf("及格\\n" )
case grade == "F":
fmt.Printf("不及格\\n" )
default:
fmt.Printf("差\\n" )

fmt.Printf("你的等级是 %s\\n", grade )

Type Switch

关于switch也可以用于type检查,switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型

switch x.(type)
case type:
statement(s)
case type:
statement(s)
/* 你可以定义任意个数的case */
default: /* 可选 */
statement(s)

例子

package main

import "fmt"

type go_class struct
class_name string
class_stage int


func main()
var g go_class
g.class_name = "shineyork go class"
g.class_stage = 1
sw(10)
sw("s")
sw(g)

func sw(x interface)
switch x.(type) // 带初始化语句
case nil:
fmt.Println(" x 的类型 nil\\r\\n")
case int:
fmt.Println("x 是 int 型")
case float64:
fmt.Println("x 是 float64 型")
case func(int) float64:
fmt.Println("x 是 func(int) 型")
case bool, string:
fmt.Println("x 是 bool 或 string 型")
case go_class:
fmt.Println("x 是 go_class 型")
default:
fmt.Println("未知型")





fallthrough

var k = 0
switch k
case 0:
println("fallthrough")
/*

Go的switch非常灵活,表达式不必是常量或整数,执行的过程从上至下,直到找到匹配项;
而如果switch没有表达式,它会匹配true。
Go里面switch默认相当于每个case最后带有break,
匹配成功后不会自动向下执行其他case,而是跳出整个switch,
但是可以使用fallthrough强制执行后面的case代码。
*/

case 1:

fmt.Println("1")

default:

fmt.Println("def")

效果:

D:\\phpStudy\\PHPTutorial\\WWW\\go\\bin>go run shineyork/02/
fallthrough
1

switch不写条件的时候当if与else运用

var n = 0
switch //省略条件表达式,可当 if...else if...else
case n > 0 && n < 10:
fmt.Println("i > 0 and i < 10")
case n > 10 && n < 20:
fmt.Println("i > 10 and i < 20")
default:
fmt.Println("def")

2.2. for

Go语言的For循环有3中形式,只有其中的一种使用分号。

for init; condition; post  

for condition

for

init: 一般为赋值表达式,给控制变量赋初值;

condition: 关系表达式或逻辑表达式,循环控制条件;

post: 一般为赋值表达式,给控制变量增量或减量。

for语句执行过程如下:

①先对表达式 init 赋初值;

②判别赋值表达式 init 是否满足给定 condition 条件,若其值为真,满足循环条件,则执行循环体内语句,然后执行 post,进入第二次循环,再判别 condition;否则判断 condition 的值为假,不满足条件,就

终止for循环,执行循环体外语句。

例子:

func main() 
s := "abc123"
for i, n := 0, length(s); i < n; i++ // 常见的 for 循环,支持初始化语句。
println(s[i])

n := len(s)
for n > 0 // 替代 while (n > 0)
n--
println(s[n]) // 替代 for (; n > 0;)

for // 替代 while (true)
println(s) // 替代 for (;;)


func length(s string) int
println("call length.")
return len(s)

不要期望编译器能理解你的想法,在初始化语句中计算出全部结果是个好主意。

3. 指针

关于go中的指针实际上和PHP的 " & " 功能很是相似,不过还是有一点区别go语言中的指针只需要记住两个符号:&(取地址)和*(根据地址取值)

要搞明白Go语言中的指针需要先知道3个概念:指针地址、指针类型和指针取值。

在整之前回顾PHP中的&

在PHP中的&特点就是会引用

<?php
$a = 0;
$b = &$a;
$b++;
echo $a;
?>

输出结果为 1 ;

3.1. 指针地址和指针类型

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用&字符放在变量前面对变量进行“取地址”操作。 Go语言中的值类型(int、float、bool、string、array、struct)都有对应的指针类

型,如:*int、*int64、*string等。

取变量指针的语法如下:

ptr := &v // v的类型为T

其中:

v:代表被取地址的变量,类型为T

ptr:用于接收地址的变量,ptr的类型就为*T,称做T的指针类型。*代表指针。

例子

var a int = 10
b := &a
fmt.Println(b) // 0xc0000100a0
fmt.Println(a) // 10
fmt.Println(&b) // 0xc000006028
效果:0xc0000100a0

3.2. 指针取值

在对普通变量使用&操作符取地址后会获得这个变量的指针,然后可以对指针使用*操作,也就是指针取值,代码如下。

func main() 

//指针取值
a := 10
b := &a // 取变量a的地址,将指针保存到b中
c := *b // 指针取值(根据指针去内存取值)
fmt.Printf("type of b:%T\\n", b) // type of b:*int
fmt.Printf("type of c:%T\\n", c) // type of c:int
fmt.Printf("value of c:%v\\n", c) // value of c:10
var t1 int = 10
a1 := &t1
*a1 = 100
fmt.Println(t1)

总结: 取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。

变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:

1. 对变量进行取地址(&)操作,可以获得这个变量的指针变量。

2. 指针变量的值是指针地址。

3. 对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值。

func main() 
a := 10
test1(a)
fmt.Println(a)
test2(&a)
fmt.Println(a)

func test1(x int)
x = 0

func test2(a *int)
*a = 0

3.3. 空指针

当一个指针被定义后没有分配到任何变量时,它的值为 nil

空指针的判断

var a *int

fmt.Println(a)

4. 数组Array

1. 数组:是同一种数据类型的固定长度的序列。

2. 数组定义:var a [len]int,比如:var a [5]int,数组长度必须是常量,且是类型的组成部分。一旦定义,长度不能变。

3. 长度是数组类型的一部分,因此,var a[5] int和var a[10]int是不同的类型。

4. 数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1

for i := 0; i < len(a); i++  

for index, v := range a

5. 访问越界,如果下标在数组合法范围之外,则触发访问越界,会panic

6. 数组是值类型,赋值和传参会复制整个数组,而不是指针。因此改变副本的值,不会改变本身的值。

7. 支持 "=="、"!=" 操作符,因为内存总是被初始化过的。

8. 指针数组 [n]*T,数组指针 *[n]T。

4.1. 数组定义

一维数组:

全局的定义方式也适合局部

全局:

var arr0 [5]int = [5]int1, 2, 3

var arr1 = [5]int1, 2, 3, 4, 5

var arr2 = [...]int1, 2, 3, 4, 5, 6

var str = [5]string3: "hello world", 4: "tom"

局部:

a := [3]int1, 2 // 未初始化元素值为 0。
b := [...]int1, 2, 3, 4 // 通过初始化值确定数组长度。
c := [5]int2: 100, 4: 200 // 使用索引号初始化元素。
d := [...]struct

name string
age uint8

"user1", 10, // 可省略元素类型。
"user2", 20, // 别忘了最后一行的逗号。

多维数组:

全局的定义方式也适合局部

全局

var arr0 [5][3]int
var arr1 [2][3]int = [...][3]int1, 2, 3, 7, 8, 9

局部:

a := [2][3]int1, 2, 3, 4, 5, 6

b := [...][2]int1, 1, 2, 2, 3, 3 // 第 2 纬度不能用 "..."。

遍历

var f [2][3]int = [...][3]int1, 2, 3, 7, 8, 9

for k1, v1 := range f
for k2, v2 := range v1
fmt.Printf("(%d,%d)=%d ", k1, k2, v2)

fmt.Println()

4.2. 数组定义

形参方式

void myFunction(param [10]int)

void myFunction(param []int)

4.3. 与数组相关的函数

len -- 来求长度,比如string、array、slice、map、channel ,返回长度

实例:

var usernames [5]string = [5]string"shineyork", "cara"

fmt.Println(len(usernames))

5. 切分Slice

Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大

需要说明,slice 并不是数组或数组指针。它通过内部指针和相关属性引用数组片段,以实现变长方案。

1. 切片:切片是数组的一个引用,因此切片是引用类型。但自身是结构体,值拷贝传递。
2. 切片的长度可以改变,因此,切片是一个可变的数组。
3. 切片遍历方式和数组一样,可以用len()求长度。表示可用元素数量,读写操作不能超过该限制。
4. cap可以求出slice最大扩张容量,不能超出数组限制。0 <= len(slice) <= len(array),其中array是slice引用的数组。
5. 切片的定义:var 变量名 []类型,比如 var str []string var arr []int。
6. 如果 slice == nil,那么 len、cap 结果都等于 0

5.1. 切分Slice定义

1. 声明一个未指定大小的数组来定义切片

var identifier \\[]type

2. 切片不需要说明长度 或者使用make()函数来创建切片

var slice1 []type = make([]type, len)

也可以简写为

slice1 := make([]type, len)

也可以指定容量,其中capacity为可选参数

make([]T,length,capacity)

这里的len是数组的长度并且也是切片的初始长度

示例:

//1.声明切片
var s1 []int
// 2.:=
s2 := []int
// 3.make()
var s3 []int = make([]int, 0)
var s4 []int = make([]int, 0, 0)
fmt.Println(s1, s2, s3, s4)

5.2. 切分Slice初始化

// 直接初始化切片,[]表示是切片类型,1,2,3初始化值依次是1,2,3.其cap=len=3

var arr = [...]int0, 1, 2, 3, 4, 5, 6, 7, 8, 9

arr2 := [...]int9, 8, 7, 6, 5, 4, 3, 2, 1, 0

// 初始化切片slice8,是数组arr的引用

var slice3 []int = arr[:]

slice8 := arr[:]

// 将arr中从下标start到end的元素创建为一个新的切片

var slice0 []int = arr[start:end]

slice5 := arr[start:end]

// 默认 end 时将表示一直到arr的最后一个元素

var slice2 []int = arr[start:]

slice7 := arr[start:]

// 默认 start 时将表示一直到arr的最后一个元素

var slice1 []int = arr[:end]

slice6 := arr[:end]

// 通过内置函数make()初始化切片s,[]int 标识为其元素类型为int的切片

s :=make([]int,len,cap)

示例:

arr := [...]int9, 8, 7, 6, 5, 4, 3, 2, 1, 0

slice5 := arr[2:8]

slice6 := arr[0:6] //可以简写为 slice := arr[:end]

slice7 := arr[5:10] //可以简写为 slice := arr[start:]

slice8 := arr[0:len(arr)] //slice := arr[:]

slice9 := arr[:len(arr)-1] //去掉切片的最后一个元素

fmt.Printf("局部变量: arr %v\\n", arr)

fmt.Printf("局部变量: slice5 %v\\n", slice5)

fmt.Printf("局部变量: slice6 %v\\n", slice6)

fmt.Printf("局部变量: slice7 %v\\n", slice7)

fmt.Printf("局部变量: slice8 %v\\n", slice8)

fmt.Printf("局部变量: slice9 %v\\n", slice9)

值得注意的是读写操作实际目标是底层数组,只需注意索引号的差别。

data := [...]int0, 1, 2, 3, 4, 5

s := data[2:4]

s[0] += 100



s[1] += 200

fmt.Println(s)

fmt.Println(data)

效果

C:\\Users\\shineyork>go run shineyork/02/

[102 203]

[0 1 102 203 4 5]

5.3. cap与len

len -- 来求长度,比如string、array、slice、map、channel ,返回长度

cap -- capacity是容量的意思,用于返回某个类型的最大容量(只能用于切片和 map)

示例:
s1 := []int0, 1, 2, 3, 8: 100 // 通过初始化表达式构造,可使用索引号。

fmt.Println(s1, len(s1), cap(s1))

s2 := make([]int, 6, 8) // 使用 make 创建,指定 len 和 cap 值。

fmt.Println(s2, len(s2), cap(s2))

s3 := make([]int, 6) // 省略 cap,相当于 cap = len。

fmt.Println(s3, len(s3), cap(s3))

效果:

[0 1 2 3 0 0 0 0 100] 9 9
[0 0 0 0 0 0] 6 8
[0 0 0 0 0 0] 6 6

5.4. 操作方法

5.4.1. append 元素的添加与删除 元素的添加与删除

s := []int0, 1, 2, 3
s = append(s, 4)
fmt.Println(s)
i := 2
s = append(s[:i], s[i+1:]...)
fmt.Println(s)

需要注意:append :向 slice 尾部添加数据,返回新的 slice 对象。

s1 := make([]int, 0, 5)
fmt.Printf("%p\\n", &s1)
s2 := append(s1, 1)
fmt.Printf(go语言进阶之路

1.1Go语言基础环境配置1.2VScode中Go的相关插件的安装1.3Go语言基础之1--标识符、关键字、变量和常量、数据类型、Go的基本程序结构、Golang的特性2.1Go语言基础之2--字符串详解2.2Go语言基础之3--时间和日期序列2.3Go语言基础之4--流程... 查看详情

好好学习go语言,go语言基础学习目录★√

好好学习GO语言,GO语言基础学习目录★√GO语言好好学习GO语言,GO语言基础学习目录★√一、GO语言基础学习01-Go简介02-标识符与变量03-数据类型04-流程控制05-运算符6-值类型-1-数值类型06-值类型-2-字符串06-值类型-3-数组06-值类型-4-... 查看详情

好好学习go语言,go语言基础学习目录★√

好好学习GO语言,GO语言基础学习目录★√GO语言好好学习GO语言,GO语言基础学习目录★√一、GO语言基础学习01-Go简介02-标识符与变量03-数据类型04-流程控制05-运算符6-值类型-1-数值类型06-值类型-2-字符串06-值类型-3-数组06-值类型-4-... 查看详情

1.1go微服务实战(go语言基础)---go语言程序基础

第1章 Go语言程序基础1.1 Hello,World!1.2 变量、指针及赋值 1.2.1 变量和常量 1.2.2 指针 1.2.3 赋值1.3 包及作用域1.4 选择和循环1.5 垃圾回收     查看详情

从零开始——go语言基础语法

学习任何一门语言,都要学习好基础,把基础打牢,那些框架对你来说都是工具,你自己的基础好,懂得了他们的原理,自己就可以创造更优秀的框架。现在带大家学习GO语言的基础语法,让您的编程路上不迷茫。JetBrainsGoLand2020... 查看详情

go语言基础之包(代码片段)

Go语言基础之包在工程化的Go语言开发项目中,Go语言的源码复用是建立在包(package)基础之上的。本文介绍了Go语言中如何定义包、如何导出包的内容及如何导入其他包。Go语言的包(package)包介绍包(package)是多个Go源码的集... 查看详情

go语言第十四篇:go语言基础总结

Go语言类型转换类型转换用于将一种数据类型的变量转换为另外一种类型的变量,Go语言类型转换基本格式如下:type_name(expression)type_name为类型,expression为表达式。实例以下实例中将整形转化为浮点型,并计算结果,将结果赋值... 查看详情

go语言学习-基础知识(代码片段)

go程序的基本结构一个可以最简单的可运行的go程序需要满足下面两个条件:有一个main()函数main()函数在main包中例如:在go语言中的helloworld程序如下://main.gopackagemainfuncmain()println("helloworld");程序中的package关键字,用来声明文件所属... 查看详情

go基础--笔记(代码片段)

Go语言基础部分学习笔记:(系统不支持插入Go代码下面插入的代码选用的格式是C++......)以下内容更多的并非解释相关知识是什么意思,而是给有过其他语言基础的人看看Go语言的语法格式,如何快速使用Go代码可以去Github下载... 查看详情

go语言基础

一、区别于其他语言的特点:清晰并且简洁、并行(线和goroutines)、Channel、快速、安全、标准格式化、类型后置(varaint)、UTF-8、开源、开心Erlang[7]与Go在部分功能上类似。Erlang和Go之间主要的区别是Erlang是函数式语言,而Go是命... 查看详情

go语言学习--基础篇

..."helloworld!!!")}从第一个go程序中,我们可以初始认识一下go语言的程序结构1,package声明go语言的包,2,import导入包3,funcmain( 查看详情

go语言基础介绍

 Go是一个开源的编程语言。Go语言被设计成一门应用于搭载Web服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。目前,Go最新发布版本为1.10.        Go语言可以运行在Linux、FreeBSD、Ma... 查看详情

go语言基础介绍

 Go是一个开源的编程语言。Go语言被设计成一门应用于搭载Web服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。目前,Go最新发布版本为1.10.        Go语言可以运行在Linux、FreeBSD、Ma... 查看详情

go语言学习go语言基础语法

...行代表一个语句结束。每个语句不需要像C家族中的其它语言一样以分号;结尾,因为这些工作都将由Go编译器自动完成。如果你打算将多个语句写在同一行,它们则必须使用;人为区分,但在实际开发中我们并不鼓励这种做法。以... 查看详情

go语言基础

...行代表一个语句结束。每个语句不需要像C家族中的其它语言一样以分号;结尾,因为这些工作都将由Go编译器自动完成。如 查看详情

go语言学习——go语言基础之流程控制二

使用switch语句方便对大量的值进行条件判断packagemainimport"fmt"//流程控制之跳出for循环funcmain()//当i=5时就跳出for循环fori:=0;i<10;i++ifi==5break//跳出for循环 查看详情

go语言基础(代码片段)

Go语言基础(二)跟着上篇,继续看Go基础一、变量作用域与C类似,有全局变量、局部变量、形参之分packagemainimport"fmt"//全局变量varc=20funcmain()//局部变量a:=10b:=20fmt.Println("a=",a)fmt.Println("a+b=",sum(a,b))fmt.Println("c=",c)//形参funcsum(aint,bi... 查看详情

go语言学习--基础篇

...类型           go语言中bool类型只有两个值:true和false;不像其它语言中0和1也可以表示布尔类型,这在go语言中是不允许的,另外定义一个bool类型,默认值为false&n 查看详情