您的位置:首页 > 房产 > 建筑 > go语言入门教程

go语言入门教程

2024/12/23 8:52:58 来源:https://blog.csdn.net/qq_58220428/article/details/140060804  浏览:    关键词:go语言入门教程

Go语言最初由Google公司的Robert Griesemer、Ken Thompson和Rob Pike三个大牛于2007年开始设计发明,他们最终的目标是设计一种适应网络和多核时代的C语言。所以Go语言很多时候被描述为“类C语言”,或者是“21世纪的C语言”,当然从各种角度看,Go语言确实是从C语言继承了相似的表达式语法、控制流结构、基础数据类型、调用参数传值、指针等诸多编程思想。但是Go语言更是对C语言最彻底的一次扬弃,它舍弃了C语言中灵活但是危险的指针运算,还重新设计了C语言中部分不太合理运算符的优先级,并在很多细微的地方都做了必要的打磨和改变。

目录

一、基础语法

1.1 变量声明

1.2 常量声明

1.3 nil与零值

二、方法和包

2.1 Go中方法的定义

2.2 包与可见性

2.3 指针

三、条件、循环、分支

3.1 条件语句

3.2 循环语句

3.3 分支语句

四、数组、切片、字典

4.1 数组

4.1.1 切片

4.2 字典

五、并发与多线程(Goroutine)

5.1 go关键字

5.2 Channel

一、基础语法

1.1 变量声明

Go语言中有两种方式声明变量

1. 使用var关键字声明,且需要注意的是,与大多数强类型语言不同,Go语言的声明变量类型位于变量名称的后面,Go语句结束不需要分号。

var num int
var result string = "this is result"

2. 使用 := 赋值

num := 3 等同于 var num int = 3

其中变量的类型会根据右侧的值进行匹配,例如"3"会匹配为int,"3.0"会匹配为float64,"result"会匹配为string。

1.2 常量声明

使用const来声明一个常量,一个常量在声明后不可改变。

const laugh string = "go"

1.3 nil与零值

只声明未赋值的变量,其值为nil,类似于C/C++中的“NULL/nullptr”。

没有明确初始值的变量声明会被赋予它们的零值。

零值是:

若为数值类型 则为0

若为布尔类型 则为false

若为字符串类型 则为 ""(空字符串)

二、方法和包

2.1 Go中方法的定义

使用func关键字来定义一个方法,后面跟方法名,然后是参数,返回值(如果有的话,没有返回值则不写)。

func MethodName(p1 Parm, p2 Parm) int{}

//学习一个语言应该从Hello World开始!
package mainimport "fmt"func main() {fmt.Println("Hello World!")// Hello World!fmt.Println(add(3, 5)) //8var sum = add(3, 5)
}func add(a int, b int) int{return a+b;
}

多个返回值

Go 函数与其他编程语言一大不同之处在于支持多返回值,这在处理程序出错的时候非常有用。例如,如果上述 add 函数只支持非负整数相加,传入负数则会报错。

//返回值只定义了类型 没有定义返回参数
func add(a, b int) (int, error) {if a < 0 || b < 0 {err := errors.New("只支持非负整数相加")return 0, err}a *= 2b *= 3return a + b, nil
}//返回值还定义了参数 这样可以直接return 并且定义的参数可以直接使用 return时只会返回这两个参数
func add1(a, b int) (z int, err error) {if a < 0 || b < 0 {err := errors.New("只支持非负整数相加")return   //实际返回0 err 因为z只定义没有赋值 则nil值为0}a *= 2b *= 3z = a + breturn //返回 z err
}func main()  {x, y := -1, 2z, err := add(x, y)if err != nil {fmt.Println(err.Error())return}fmt.Printf("add(%d, %d) = %d\n", x, y, z)
}

2.2 包与可见性

在 Go 语言中,无论是变量、函数还是类属性和成员方法,它们的可见性都是以包为维度的,而不是类似传统面向编程那样,类属性和成员方法的可见性封装在所属的类中,然后通过 privateprotected 和 public 这些关键字来修饰其可见性。

Go 语言没有提供这些关键字,不管是变量、函数,还是自定义类的属性和成员方法,它们的可见性都是根据其首字母的大小写来决定的,如果变量名、属性名、函数名或方法名首字母大写,就可以在包外直接访问这些变量、属性、函数和方法,否则只能在包内访问,因此 Go 语言类属性和成员方法的可见性都是包一级的,而不是类一级的。

假如说一个名为domain的文件夹下有3个.go文件,则三个文件中的package都应为domain,其中程序的入口main方法所在的文件,包为main

//定义了此文件属于 main 包
package main//通过import导入标注库中包
import "fmt"func main() {fmt.Println("Hello World!")// Hello World!fmt.Println(add(3, 5)) //8var sum = add(3, 5)
}func add(a int, b int) int{return a+b;
}

2.3 指针

对于学过C语言的同学来说,指针还是比较熟悉的。指针也许可以这样理解,其实就是一个在内存中实际的16进制的地址值,引用变量的值通过此地址去内存中取出对应的真实值。


func main() {i := 0//使用&来传入地址fmt.Println(&i) //0xc00000c054var a, b int = 3 ,4//传入 0xc00000a089 0xc00000a090fmt.Println(add(&a, &b)) 
}//使用*来声明一个指针类型的参数与使用指针
func add(a *int, b *int)int{//接收到 0xc00000a089 0xc00000a090//前往 0xc00000a089位置查找具体数据 并取赋给xx := *a//前往 0xc00000a090位置查找具体数据 并取赋给yy := *breturn x+y
}

三、条件、循环、分支

3.1 条件语句

// if
if condition { // do something 
}// if...else...
if condition { // do something 
} else {// do something 
}// if...else if...else...
if condition1 { // do something 
} else if condition2 {// do something else 
} else {// catch-all or default 
}

3.2 循环语句

sum := 0 //普通for循环
for i := 1; i <= 100; i++ { sum += i 
}//无限循环
for{sum++if sum = 100{break;}
}//带条件的循环
for res := sum+1; sum < 15{sum++res++
}//使用kv循环一个map或一个数组  k为索引或键值 v为值 k、v不需要时可以用_带替
for k, v := range a {fmt.Println(k, v)
}

3.3 分支语句

score := 100
switch score {
case 90, 100:fmt.Println("Grade: A")
case 80:fmt.Println("Grade: B")
case 70:fmt.Println("Grade: C")
case 65:fmt.Println("Grade: D")
default:fmt.Println("Grade: F")
}

四、数组、切片、字典

4.1 数组

数组功能与C/C++语言类似,都是长度不可变,并且可以使用多维数组,也可以通过arrays[i]来存储或获取值。

//声明
var nums [3]int 
//声明并初始化
var nums = [3]int{1,2,3} <==> nums:=[3]int{1,2,3}//使用
for sum := 0, i := 0;i<10{sum += nums[i]i++
}
//修改值
num[0] = -1

数组使用较为简单,但是存在着难以解决的问题:长度固定

例如在程序中需要一个数据结构来存储获取到的所有用户,因为用户数量是会随着时间变化的,但是数组其长度却不可改变,所以数组并不适合存储长度会发生改变的数据,因此在Go语言中通过使用切片来解决以上问题。

4.1.1 切片

切片与数组最大的不同就是切片不用声明长度。但是切片与数组并非毫无关系,数组可以看作是切片的底层数组,而切片则可以看作是数组某个连续片段的引用。切片可以只使用数组的一部分元素或者整个数组来创建,甚至可以创建一个比所基于的数组还要大的切片。

切片的长度就是它所包含的元素个数

切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数

切片 s 的长度和容量可通过表达式 len(s) 和 cap(s) 来获取

创建切片

//声明一个数组
var nums =[3]int{1, 2, 3}
//0.直接声明
var slice =[]int{0, 1, 2}//1.从数组中引用切片 其中a:b是指包括a但不包括b
var slice1 = nums[0:2] //{1,2}
//如果不写的则默认为0(左边)或最大值(右边)
var slice2 = slice1[:2] <==> var slice2 = slice1[0:] <==>var slice2 = slice1[:]//2.使用make创建Slice 其中int为切片类型,4为其长度,5为容量
slice3 := make([]int, 5)
slice4 := make([]int, 4, 5)

动态操作切片

//使用append向切片中动态的添加元素
func append(s []T, vs ...T) []Tslice5 := make([]int, 4, 5) //{0, 0, 0, 0}
slice5 = append(slice5, 1) //{0,0,0,0,1}//删除第一个0
sliece5 = slice5[1:]

切片的常用场景

//声明切片
var userIds = []int{}
//模拟获取所有用户ID
for i := 0; i< 100{userIds = append(userIdS, i);i++;
}
//对用户信息进行处理
for k,v := range userIds{userIds[k] = v++
}

4.2 字典

字典也可称为 ‘键值对’ 或 ‘key-value’,是一种常用的数据结构,C++中有各种map接口,常用的有map、unordered_map、set、unordered_set等。在Go中通过使用字典来实现键值对的存储,字典是无序的,所以不会根据添加顺序来保证数据的顺序。


//string为键类型,int为值类型
maps := map[string]int{"java" : 1,"go" : 2,"python" : 3,
}//还可以通过make来创建字典 100为其初始容量 超出可扩容
maps = make(map[string]int, 100)

字典的使用场景


//直接使用
fmt.Println(maps["java"]) //1//赋值
maps["go"] = 4//取值 同时判断map中是否存在该键 ok为bool型
value, ok := maps["one"] 
if ok { // 找到了// 处理找到的value 
}//删除
delete(testMap, "four")

五、并发与多线程(Goroutine)

对于任何一个优秀的语言来说,并发处理的能力都是决定其优劣的关键。在Go语言中,通过Goroutine来实现并发的处理。

5.1 go关键字

func say(s string) {fmt.Println(s)
}func main() {//通过 go 关键字新开一个协程go say("world")say("hello")
}

5.2 Channel

多协程之间通过Channel进行通信,从功能上可以类比为Java的volatile关键字。

ch := make(chan int) 声明一个int型的Channel,两个协程之间可以通过ch进行int数据通信,

通过Channel进行数据传输。


ch <- v    // 将 v 发送至信道 ch。
v := <-ch  // 从 ch 接收值并赋予 v。
package mainimport "fmt"func sum(s []int, c chan int) {sum := 0for _, v := range s {sum += v}c <- sum // 将和送入 c
}//对于main方法来说 相当于就是开启了一个协程
func main() {s := []int{7, 2, 8, -9, 4, 0}c := make(chan int)//通过go关键字开启两个协程 将chaneel当做参数传入go sum(s[:len(s)/2], c)go sum(s[len(s)/2:], c)//通过箭头方向获取或传入信息x, y := <-c, <-c // 从 c 中接收fmt.Println(x, y, x+y)
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com