【GO语言入门】

前言

Go语言是一门很年轻的语言,2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。

Go 语言特色

  • 简洁、快速、安全
  • 并行、有趣、开源
  • 内存管理、数组安全、编译迅速

Go 语言用途

Go 语言被设计成一门应用于搭载 Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。

对于高性能分布式系统领域而言,Go 语言无疑比大多数其它语言有着更高的开发效率。它提供了海量并行的支持,这对于游戏服务端的开发而言是再好不过了。

package main	//必须在main文件夹下

import "fmt"	//必须在存fmt包

func main() {
    fmt.Println("Hello, World!")
}

要执行 Go 语言代码可以使用 go run 命令。

$ go run hello.go 
hello world!

此外我们还可以使用 go build 命令来生成二进制文件:

$ go build hello.go 
$ ls
hello    hello.go
$ ./hello 
Hello, World!

Go语言接受了函数式编程的一些想法,支持匿名函数与闭包。Go语言接受了以Erlang语言为代表的面向消息编程思想,支持goroutine和通道,并推荐使用消息而不是共享内存来进行并发编程。总体来说,Go语言是一个非常现代化的语言,精小但非常强大。

Go 语言最主要的特性:

  • 自动垃圾回收
  • 更丰富的内置类型
  • 函数多返回值
  • 错误处理
  • 匿名函数和闭包
  • 类型和接口
  • 并发编程
  • 反射
  • 语言交互性

Go 语言结构

func main() 是程序开始执行的函数。main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有 init() 函数则会先执行该函数)。

Print 和 Println 这两个函数也支持使用变量,如:fmt.Println(arr)。如果没有特别指定,它们会以默认的打印格式将变量 arr 输出到控制台。

package main

import “fmt”

func main()
{ // 错误,{ 不能在单独的行上
fmt.Println(“Hello, World!”)
}

关于包,根据本地测试得出以下几点:

  • 文件名与包名没有直接关系,不一定要将文件名与包名定成同一个。
  • 文件夹名与包名没有直接关系,并非需要一致。
  • 同一个文件夹下的文件只能有一个包名,否则编译报错。

Go开发中间件

现在Go语言成了编写中间件的优先选择,之前都是java开发的中间件

Go语言支持高并发,支持协程(又名纤程)goroutine

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dfSOeaDr-1656854158713)(GO.assets/image-20220619192920421.png)]

Google(K8s的开发)、Facebook、腾讯(docker容器花)、百度、京东、小米、360

美团、滴滴、新浪、阿里、七牛做消息推送、监控的、容器化等。

总之,golang特别适合也逐渐用于做网络并发的服务。

一个优秀的go语言工程师的薪资待遇30k起步

Go语法



Go程序执行

在这里插入图片描述


go build -o hello.exe demo.exe //编译为exe执行文件时可以额外指定名字

Go风格

注意代码风格(也会报错)

不需要分号结尾

多余的变量、多余的包都会报错

注释有单行、多行、块注释(跟idea基本一样)

控制台命令:gofmt -w test.go //将格式化后的代码写入源文件

Go语言的API

包括在线、离线的源码查看方式

英文文档:http://docscn.studygolang.com/pkg

中文文档:https://studygolang.com/pkgdoc

菜鸟教程:https://www.runoob.com/go/go-structures.html

Go 并发

Go 语言支持并发,我们只需要通过 go 关键字来开启 goroutine 即可。

goroutine 是轻量级线程,goroutine 的调度是由 Golang 运行时进行管理的。

goroutine 语法格式:

go 函数名( 参数列表 )

例如:

go f(x, y, z)

开启一个新的 goroutine:

f(x, y, z)

Go 允许使用 go 语句开启一个新的运行期线程, 即 goroutine,以一个不同的、新创建的 goroutine 来执行一个函数。 同一个程序中的所有 goroutine 共享同一个地址空间。

package main

import (
    "fmt"
    "time"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    go say("world")
    say("hello")
}

执行以上代码,你会看到输出的 hello 和 world 是没有固定先后顺序。因为它们是两个 goroutine 在执行:

world
hello
hello
world
world
hello
hello
world
world
hello

通道(channel)

通道(channel)是用来传递数据的一个数据结构。

通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。操作符 <- 用于指定通道的方向,发送或接收。如果未指定方向,则为双向通道。

通道缓冲区

通道可以设置缓冲区,通过 make 的第二个参数指定缓冲区大小:

ch := make(chan int, 100)

带缓冲区的通道允许发送端的数据发送和接收端的数据获取处于异步状态,就是说发送端发送的数据可以放在缓冲区里面,可以等待接收端去获取数据,而不是立刻需要接收端去获取数据。

不过由于缓冲区的大小是有限的,所以还是必须有接收端来接收数据的,否则缓冲区一满,数据发送端就无法再发送数据了。

注意:如果通道不带缓冲,发送方会阻塞直到接收方从通道中接收了值。如果通道带缓冲,发送方则会阻塞直到发送的值被拷贝到缓冲区内;如果缓冲区已满,则意味着需要等待直到某个接收方获取到一个值。接收方在有值可以接收之前会一直阻塞。

package main

import "fmt"

func main() {
    // 这里我们定义了一个可以存储整数类型的带缓冲通道
        // 缓冲区大小为2
        ch := make(chan int, 2)

        // 因为 ch 是带缓冲的通道,我们可以同时发送两个数据
        // 而不用立刻需要去同步读取数据
        ch <- 1
        ch <- 2

        // 获取这两个数据
        fmt.Println(<-ch)
        fmt.Println(<-ch)
}
Go 遍历通道与关闭通道

Go 通过 range 关键字来实现遍历读取到的数据,类似于与数组或切片。格式如下:

v, ok := <-ch

如果通道接收不到数据后 ok 就为 false,这时通道就可以使用 close() 函数来关闭。

package main

import (
        "fmt"
)

func fibonacci(n int, c chan int) {
        x, y := 0, 1
        for i := 0; i < n; i++ {
                c <- x
                x, y = y, x+y
        }
        close(c)
}

func main() {
        c := make(chan int, 10)
        go fibonacci(cap(c), c)
        // range 函数遍历每个从通道接收到的数据,因为 c 在发送完 10 个
        // 数据之后就关闭了通道,所以这里我们 range 函数在接收到 10 个数据
        // 之后就结束了。如果上面的 c 通道不关闭,那么 range 函数就不
        // 会结束,从而在接收第 11 个数据的时候就阻塞了。
        for i := range c {
                fmt.Println(i)
        }
}

对于一个切片,可以看作由一个左指针和一个右指针以及capacity组合而成

array = []int{1,2,3,4,5,6,7,8,9}

// 从array取,左指针索引为0,右指针为5,切片是从array切的,
// 而且cap函数只计算左指针到原array最后的值的个数
slice = array[0:5] // slice ==> {1, 2, 3, 4, 5}
cap(slice) // == 9,因为左指针索引为0,到结尾有9个数,cap为9

slice = slice[2:] // slice ==> {3, 4, 5}

基本数据类型

在这里插入图片描述

go语言是强类型语言

包括

基本数据类型:数值、字符、不二、字符串

派生数据类型:指针、数组、结构体、管道、函数、切片、接口、map

var age int		//声明age变量
age = 19		//为age变量赋值
fmt.Println("age=",age)	//输出使用变量
//可以直接指定类型(可以赋初值也可以不赋采用默认值)、也可以提类型推断
var age int = 20
fmt.Println("age=",age)

var length int
fmt.Println("lenght=",length)

var name = "tom"
fmt.Println("name=",name)
//也可以采用省略 var关键字的方式
sex :="男"	//这种写法非常简单
fmt.Println("sex=",sex)
//局部变量:定义在函数内部
//一次性声明多个变量
var n1,n2,n3 int
fmt.Println("n1=",n1)
fmt.Println("n2=",n2)
fmt.Println("n3=",n2)

//一次性声明多个变量并赋值
var n4,n5,n6 = 10 ,"jack",7,8
fmt.Println("n4=",n4)
fmt.Println("n5=",n5)
fmt.Println("n6=",n6)

var n7,n8 := 9.9,100.9
fmt.Println("n7=",n7)
fmt.Println("n8=",n8)

//全局变量:定义在函数外
var n9 := 90
var(
	n10 = “iuhf”
)

进制表示与进制转换需要熟练掌握

十进制(D)、二进制(B)、八进制(Q)、十六进制(H)

整数类型
//有符号数据类型:
int8int16int32int64
//无符号数据类型:
uint8uint16uint32uint
//其他数据类型(bit长度自适应系统)
intuintrunebyte
//Golang中整型默认为int

在这里插入图片描述


在这里插入图片描述


//定义一个整数类型
var num1 int8 = 120
fmt.Println(num1)
var num2 uint8 = 120
fmt.Println(num2)

var num3 = 28
fmt.Printf("num3的数据类型是:%T\n",num3)
fmt.Println("num3的字节数:",unsafe.Sizeof(num3))
浮点类型

在这里插入图片描述


package main

import "fmt"

func main(){
	var num1 float32 = 3.14
	fmt.Println(num1)
	var num2 float32 = -3.14
	fmt.Println(num2)
	var num3 float32 = 314E+2
	fmt.Println(num3)
	var num4 float32 = 314e+2
	fmt.Println(num4)
	var num5 float32 = 314E-2
	fmt.Println(num5)
	var num6 float32 = 314e-2
	fmt.Println(num6)

	var num7 float32 = 256.0000000012
	fmt.Println(num7)
	var num8 float64 = 256.0000000012
	fmt.Println(num8)

	//默认的浮点类型是float64
	var num9 = 3.17
	fmt.Printf("%T",num9)
}
字符类型
package main

import "fmt"

func main(){
	var c1 byte = 'a'
	fmt.Println(c1)

	var c2 byte = '6'
	fmt.Println(c2)

	var c3 byte = '('
	fmt.Println(c3)

	//	查看UTF-8编码表:
	//http://www.mytju.com/classcode/tools/encode_utf8.asp
	//汉字底层对应的Unicode码
	var c4 int = '中'		//对应的整型为20013
	fmt.Println(c4)
//golang 的字符对应的使用的是utf-8编码(utf-8是Unicode的一种编码方案)

	var c5 byte = 'A'
	fmt.Printf("c5对应的字符为:%C",c5)
}

查看UTF-8编码表:
http://www.mytju.com/classcode/tools/encode_utf8.asp

布尔数据类型

只允许true或false,占一个字节, 可参与逻辑运算

import "fmt"

func main(){
   //bool
   var flag01 bool = false
   fmt.Println(flag01)

   var flag02 bool = true
   fmt.Println(flag02)

   var flag03 bool = 5 < 9
   fmt.Println(flag03)
}
字符串数据类型
package main

import "fmt"

func main() {
   var s1 string = "hello ,golang!"
   fmt.Println(s1)

   //字符串不可变,指的是字符串一旦被定义,其字符的值不可改变
   var s2 string = "abc"
   //s2[0] = 'c'  这样的操作是错误的
   fmt.Println(s2)

   //一般字符串
   var s3 string = "test"
   fmt.Println(s3)
   //特殊字符用反引符号 ` `包括起来
   var s4 string = `import "fmt"

func main(){
   //bool
   var flag01 bool = false
   fmt.Println(flag01)

   var flag02 bool = true
   fmt.Println(flag02)

   var flag03 bool = 5 < 9
   fmt.Println(flag03)
}`
   fmt.Println(s4)

   //字符串的拼接
   var s5 string = "abc" + "def"
   fmt.Println(s5)
   s5 += "hijk"
   fmt.Println(s5)

   //当一个字符串过长的时候,+保留在上一行的最后
   var s6 string = "abc" + "def"+"abc" + "def"+"abc" + "def"+
      "abc" + "def"+"abc" + "def"+"abc" + "def"+"abc" + "def"+
      "abc" + "def"+"abc" + "def"+"abc" + "def"+"abc" + "def"

   fmt.Println(s6)
}
基本数据类型的默认值
import "fmt"

func main(){
   var a int
   fmt.Println(a)	//0
   var b float32
   fmt.Println(b)	//0
   var c float64
   fmt.Println(c)	//0
   var d bool
   fmt.Println(d)	//false
   var e string
   fmt.Println(e)	//空
   fmt.Println("结束")
}
基本数据类型的转换

只有显式转换(强制转换)

在这里插入图片描述

package main

import "fmt"

func main(){
   var n int = 32
   fmt.Println(n)
   //var n2 float32 = n 这样是错误的
   //必须显式转换
   var n2 float32 = float32(n)
   fmt.Println(n2)
   //注意:n依旧是int类型,只是将n的值转为了float32
   fmt.Printf("%T\n",n)      //输出n的类型并换行

   var n3 int64 = 88888
   var n4 int8 = int8(n3)
   fmt.Println("n3=",n3)
   fmt.Println("n4=",n4)

   var n5 int32 = 12
   //要匹配等号左右的数据类型
   var n6 int64 = int64(n5) + 30
   fmt.Println(n6)

   var n7 int64 = 12
   var n8 int8 = int8(n7) + 127
   //var n9 int8 = int8(n7)+128  编译报错

   fmt.Println("n8=",n8)
}
基本数据类型转string

在这里插入图片描述


Go语言标准库文档中文版 | Go语言中文网 | Golang中文社区 | Golang中国 (studygolang.com)

方式一(经常使用)

在这里插入图片描述

var n1 int = 19
var n2 float32 = 2.34
var n3 bool = false
var n4 byte = 'a'
var s1 string = fmt.Sprintf("%d",n1)
fmt.Printf("s1对应的类型:%T,s1=%v\n",s1,s1)
fmt.Printf("s1对应的类型:%T,s1=%q\n",s1,s1)

var s2 string = fmt.Sprintf("%f",n2)
fmt.Printf("s2对应的类型:%T,s2=%v\n",s2,s2)
fmt.Printf("s2对应的类型:%T,s2=%q\n",s2,s2)

var s3 string = fmt.Sprintf("%t",n3)
fmt.Printf("s3对应的类型:%T,s3=%v\n",s3,s3)
fmt.Printf("s3对应的类型:%T,s3=%q\n",s3,s3)

var s4 string = fmt.Sprintf("%c",n4)
fmt.Printf("s4对应的类型:%T,s4=%v\n",s4,s4)
fmt.Printf("s4对应的类型:%T,s4=%q\n",s4,s4)

方式二

var n1 int = 19
var s1 string = strconv.FormatInt(int64(n1),10)    //第一个参数必须为int64,第二个参数指定什么进制
fmt.Printf("s1对应的类型:%T,s1=%q\n",s1,s1)

var n2 float32 = 2.34
//第一个参数为float64 第二个参数为输出格式 第三个参数为小数点后的数字各位为-1时采用尽可能少的小数点后数  第四个参数表示第一个参数的来源类型
var s2 string = strconv.FormatFloat(float64(n2),'f',9,32)
fmt.Printf("s2对应的类型:%T,s2=%q\n",s2,s2)

var n3 bool = true
var s3 string = strconv.FormatBool(n3)
fmt.Printf("s3对应的类型:%T,s3=%q\n",s3,s3)
将string转为基本数据类型

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

更多转换方式可以查看golang的中文文档

//golang中文文档
//https://studygolang.com/pkgdoc
func main(){
   //string-->>bool
   var s1 string = "true"
   var b bool
   //ParseBool函数有两个返回值:(value bool,err error)
   //err用_忽略
   b,_ = strconv.ParseBool(s1)
   fmt.Printf("b对应的类型:%T,b=%v\n",b,b)

   //string-->>int64
   var s2 string = "19"
   var c int64
   c,_ = strconv.ParseInt(s2,10,64)
   fmt.Printf("c对应的类型:%T,c=%v\n",c,c)

   //string-->>float64
   var s3 string = "21.2"
   var d float64
   d,_ = strconv.ParseFloat(s3,64)
   fmt.Printf("d对应的类型:%T,d=%v\n",d,d)

    //注意string转换为对应的基本类型应该具备相应的意义,否则转换后是对应基本类型的默认值
	var s4 string = "true"
	var e bool
	e,_ = strconv.ParseBool(s4)
	fmt.Printf("e对应的类型:%T,e=%v\n",e,e)
	var s5 string = "true"
	var f int64
	f,_ = strconv.ParseInt(s5,10,64)
	fmt.Printf("f对应的类型:%T,f=%v\n",f,f)
}
复杂变量
指针

基本变量

在这里插入图片描述

指针变量

关键:

& : 取出变量的地址

“*” :取出指针指向变量的值

var age int = 18
//输出变量内存的地址  &:取地址符
fmt.Println(&age)     //0xc00000a088

//定义一个指针变量  存储age变量地址的变量
var ptr *int = &age
fmt.Println(ptr)      //0xc00000a088
fmt.Println("输出指针ptr的地址",&ptr)    //0xc0000ce020

//获取指针指向变量的值
fmt.Println("获取指针指向变量的值:%v",*ptr)

在这里插入图片描述


指针细节

1、可以通过指针改变指向变量的值

var num int = 10
var ptr *int = &num
*ptr = 20
fmt.Println(num)

2、指针变量接收的一定是地址值

在这里插入图片描述

3、指针变量的地址类型必须对应

在这里插入图片描述

PS:*float32定义ptr为指向float32基本类型的指针,不能指向其他数据类型

*4、基本数据类型都有具有的指针类型,形式为【数据类型】

标识符

在这里插入图片描述


var 年龄 int = 19
fmt.Println(年龄)

var int int = 32
fmt.Println(int)   //int不是golang的保留关键字,不推荐这样

在这里插入图片描述


(利用首字母大小写控制权限)

注意:import导入语句通常放在文件开头生命语句的下面,导入的包名需要使用双引号括起来,包名是从$GOPATH/src/后开始寻径的,使用/进行路径隔离

因此要在GOPATH的路径的src目录下建立项目:
我的GOPATH设置为:D:\Program Files\GoThird
在GoThird目录下建立bin、pkg、src文件夹分别用于存放编译后的可执行文件、存放编译后生成的归档文件的、存放go源码文件(自己的项目代码)
在这里插入图片描述


关键字和预定义标识符

在这里插入图片描述


运算符
算术运算符

在这里插入图片描述


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EhHyt7MU-1656854158741)(GO.assets/image-20220702212617780.png)]


在这里插入图片描述


赋值运算符

在这里插入图片描述

交换两个变量值的方法:

方法一:int temp;//定义临时变量 temp=v1;//实现交换 v1=v2; v2=temp;

方法二:v1=v1+v2; v2=v1-v2; v1=v1-v2;

方法三:v1=v1^v2; v2=v1^v2; v1=v1^v2;

关系运算符

在这里插入图片描述

逻辑运算符

在这里插入图片描述

PS:逻辑运算符是短路运算符

运算符的优先级

在这里插入图片描述


实际使用的时候使用括号提高对应运算的优先级即可

获取终端输入

在这里插入图片描述


在这里插入图片描述


//功能:键盘录入学生的年龄、姓名、成绩、是否是VIP
	//方式一:Scanln 换行时停止扫描 返回值是扫描的条目个数和遇到的任何错误
	//Scanln类似Scan,但会在换行时才停止扫描。最后一个条目后必须有换行或者到达结束位置。
	var age int
	var name string
	var score float64
	var isVip bool
	fmt.Println("请输入学生的年龄、姓名、成绩、是否是VIP")
	fmt.Scanln(&age, &name, &score, &isVip)
	fmt.Println("学生的年龄:", age)
	fmt.Println("学生的姓名:", name)
	fmt.Println("学生的成绩:", score)
	fmt.Println("学生的是否是VIP:", isVip)
	//方式二:Scanf Scanf从标准输入扫描文本,根据format 参数指定的格式将成功读取的空白分隔的值保存进成功传递给本函数的参数。
	//返回成功扫描的条目个数和遇到的任何错误。
	fmt.Println("请输入学生的年龄、姓名、成绩、是否是VIP")
	fmt.Scanf("%d %s %f %t", &age, &name, &score, &isVip)
	fmt.Println("学生的年龄:", age)
	fmt.Println("学生的姓名:", name)
	fmt.Println("学生的成绩:", score)
	fmt.Println("学生的是否是VIP:", isVip)
	//方式三:Scan
	//Scan从标准输入扫描文本,将成功读取的空白分隔的值保存进成功传递给本函数的参数。
	//换行视为空白。返回成功扫描的条目个数和遇到的任何错误。如果读取的条目比提供的参数少,会返回一个错误报告原因。
	fmt.Println("请输入学生的年龄、姓名、成绩、是否是VIP")
	fmt.Scan(&age, &name, &score, &isVip)
	fmt.Println("学生的年龄:", age)
	fmt.Println("学生的姓名:", name)
	fmt.Println("学生的成绩:", score)
	fmt.Println("学生的是否是VIP:", isVip)
流程控制

在这里插入图片描述


其他

常量、特殊常量(iota)、条件语句、循环语句、函数、数组、

结构体、切片(slice)、范围(range)、map(集合)、接口、

错误处理、并发等等知识点

参考

https://studygolang.com/pkgdoc
https://www.runoob.com/go/go-tutorial.html
https://www.bilibili.com/video/BV1qK4y197s4?p=44&vd_source=a85877c3f8caa23c49677b5ec230d826

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值