Go基础

go mod tidy

go mod init

go语言的执行:

执行命令:go run xxx.go

生成二进制文件:go build

注意

需要注意的是 { 不能单独放在一行

func printSlice(x []int){ fmt.Printf(“len=%d cap=%d slice=%v\n,len(x),cap(x),x) } ## Go语言基础语法 在 Go 程序中,一行代表一个语句结束 字符串连接用+ Go 语言中变量的声明必须使用空格隔开 : var age int; Go 语言中使用 fmt.Sprintf 格式化字符串并赋值给新串:

Go基础 - 图1

Go数据类型

布尔型:true/false

数字类型:int,float32,float64

字符串类型:一串固定长度的字符连接起来的字符序列,Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码

派生类型:指针,数组,结构化,Channel,函数,切片,接口,Map

Go语言变量

var identifier type或者var identifier1, identifier2 type(var 变量名 类型(type))

变量声明

第一种,指定变量类型,如果没有初始化,则变量默认为零值。

第二种,根据值自行判定变量类型。

第三种,省略 var, 注意 := 左侧如果没有声明新的变量,就产生编译错误,格式:v_name := value

var ( // 这种因式分解关键字的写法一般用于声明全局变量

a int b bool )

右边的这些值以相同的顺序赋值给左边的变量,所以 a 的值是 5, b 的值是 7,c 的值是 “abc”。

这被称为 并行 或 同时 赋值。

如果你想要交换两个变量的值,则可以简单地使用 a, b = b, a,两个变量的类型必须是相同。

空白标识符 也被用于抛弃值,如值 5 在:, b = 5, 7 中被抛弃。

_ 实际上是一个只写变量,你不能得到它的值。这样做是因为 Go 语言中你必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值。

并行赋值也被用于当一个函数返回多个返回值时,比如这里的 val 和错误 err 是通过调用 Func1 函数同时得到:val, err = Func1(var1)。

Go语言常量

const 变量名 [type] = value

Go常量:iota

iota,特殊常量,可以认为是一个可以被编译器修改的常量。

iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。

iota 可以被用作枚举值:

const (
  1. a <font style="color:#666600;">=</font><font style="color:#000000;"> iota</font>
  2. b <font style="color:#666600;">=</font><font style="color:#000000;"> iota</font>
  3. c <font style="color:#666600;">=</font><font style="color:#000000;"> iota</font>
)

Go语言selece语句

select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收。

select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。

语法

Go 编程语言中 select 语句的语法如下:

select {

  1. case communication clause <font style="color:#339933;">:</font>
  2. statement<font style="color:#339933;">(</font>s<font style="color:#339933;">);</font>
  3. case communication clause <font style="color:#339933;">:</font>
  4. statement<font style="color:#339933;">(</font>s<font style="color:#339933;">);</font>
  5. /* 你可以定义任意数量的 case */
  6. default <font style="color:#339933;">:</font> /* 可选 */
  7. statement<font style="color:#339933;">(</font>s<font style="color:#339933;">);</font>
}

以下描述了 select 语句的语法:

  • 每个 case 都必须是一个通信
  • 所有 channel 表达式都会被求值
  • 所有被发送的表达式都会被求值
  • 如果任意某个通信可以进行,它就执行,其他被忽略。
  • 如果有多个 case 都可以运行,Select 会随机公平地选出一个执行。其他不会执行。否则:
    1. 如果有 default 子句,则执行该语句。
    2. 如果没有 default 子句,select 将阻塞,直到某个通信可以运行;Go 不会重新对 channel 或值进行求值。

Go循环

for init; condition; post { } for condition { } //相当于while for {} //for(;;) for key, value := range oldMap {
  1. newMap<font style="color:#666600;">[</font><font style="color:#000000;">key</font><font style="color:#666600;">]</font><font style="color:#000000;"> </font><font style="color:#666600;">=</font><font style="color:#000000;"> value</font>
}

Go语言函数

Go语言函数

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

Go数组

声明数组

Go 语言数组声明需要指定元素类型及元素个数,语法格式如下:

var variable_name [SIZE] variable_type

以上为一维数组的定义方式。例如以下定义了数组 balance 长度为 10 类型为 float32:

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}

如果设置了数组的长度,我们还可以通过指定下标来初始化元素:

// 将索引为 1 和 3 的元素初始化

balance := [5]float32{1:2.0,3:7.0}

Go指针

以下声明了整型指针数组:

var ptr [MAX]*int;

Go结构体

结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,结构体中有一个或多个成员。type 语句设定了结构体的名称。结构体的格式如下:

type struct_variable_type struct {

member definition

member definition

member definition

} 例如:

type Books struct {

title string author string subject string book_id int }

结构体指针格式:

var struct_pointer *Books

Go语言切片(Slice)

定义切片

var identifier []type 用make()函数来创建切片: var slice1 []type = make([]type, len) 也可以简写为

slice1 := make([]type, len)

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

make([]T, length, capacity)

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

切片初始化

s :=[] int {1,2,3 }

Go语言接口

Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。

/ 定义接口 /

type interface_name interface {

method_name1 [return_type] method_name2 [return_type] method_name3 [return_type] method_namen [return_type] }

/ 定义结构体 /

type struct_name struct {

/ variables / }

/ 实现接口方法 /

func (struct_name_variable struct_name) method_name1() [return_type] { / 方法实现 / }

func (struct_name_variable struct_name) method_namen() [return_type] { / 方法实现/ }

定义接口

type Phone interface {

call() } 定义结构体

type NokiaPhone struct {

} 实现接口 func (nokiaPhone NokiaPhone) call() { fmt.Println(“I am Nokia, I can call you!”) } 使用 func main() { var phone Phone

phone = new(Books)

phone.call()

}

定义接口,new一个新结构体,调用接口的方法


Go错误处理

Go 语言通过内置的错误接口提供了非常简单的错误处理机制。

error类型是一个接口类型,这是它的定义:

type error interface {
  1. <font style="color:#660066;">Error</font><font style="color:#666600;">()</font><font style="color:#000000;"> </font><font style="color:#000088;">string</font>
} 使用errors.New 可返回一个错误信息

Go 并发

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

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

goroutine 语法格式:

go 函数名( 参数列表 )

例如:

go f(x, y, z)

开启一个新的 goroutine:

f(x, y, z) Go 允许使用 go 语句开启一个新的运行期线程, 即 goroutine,以一个不同的、新创建的 goroutine 来执行一个函数。 同一个程序中的所有 goroutine 共享同一个地址空间。 func main() { go say(“hello”) say(“world”) } func say(s string){ for i := 1; i<5 ; i++{ time.Sleep(100*time.Millisecond) fmt.Println(s) } } ## 通道(channel) 通道(channel)是用来传递数据的一个数据结构。 通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。操作符 <- 用于指定通道的方向,发送或接收。如果未指定方向,则为双向通道。 ch <- v // 把 v 发送到通道 ch

v := <-ch // 从 ch 接收数据

  1. <font style="color:#880000;">// 并把值赋给 v</font>

声明一个通道很简单,我们使用chan关键字即可,通道在使用前必须先创建:

ch := make(chan int)

注意:默认情况下,通道是不带缓冲区的。发送端发送数据,同时必须有接收端相应的接收数据。

func main() { c := make(chan string) go say(“one”, c) res := <-c abc := <-c println(res) println(abc) } func say(s string, c chan string){ for i := 1; i<5 ; i++{ time.Sleep(100*time.Millisecond) fmt.Println(s) } c <- “123”
c <- “456”
} ### 通道缓冲区 通道可以设置缓冲区,通过 make 的第二个参数指定缓冲区大小: ch := make(chan int, 100)

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

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

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

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() 函数来关闭。

实例

import (

  1. <font style="color:#CC66CC;">"fmt"</font>
) func fibonacci(n int, c chan int) {
  1. x<font style="color:#339933;">,</font> y <font style="color:#339933;">:=</font> <font style="color:#CC66CC;">0</font><font style="color:#339933;">,</font> <font style="color:#CC66CC;">1</font>
  2. **for** i <font style="color:#339933;">:=</font> <font style="color:#CC66CC;">0</font><font style="color:#339933;">;</font> i < n<font style="color:#339933;">;</font> i<font style="color:#339933;">++</font> <font style="color:#339933;">{</font>
  3. c <<font style="color:#339933;">-</font> x
  4. x<font style="color:#339933;">,</font> y <font style="color:#339933;">=</font> y<font style="color:#339933;">,</font> x<font style="color:#339933;">+</font>y
  5. <font style="color:#339933;">}</font>
  6. <font style="color:#000066;">close</font><font style="color:#339933;">(</font>c<font style="color:#339933;">)</font>
} func main() {
  1. c <font style="color:#339933;">:=</font> <font style="color:#000066;">make</font><font style="color:#339933;">(</font><font style="color:#993333;">chan</font> <font style="color:#993333;">int</font><font style="color:#339933;">,</font> <font style="color:#CC66CC;">10</font><font style="color:#339933;">)</font>
  2. **go** fibonacci<font style="color:#339933;">(</font><font style="color:#000066;">cap</font><font style="color:#339933;">(</font>c<font style="color:#339933;">),</font> c<font style="color:#339933;">)</font>
  3. _// range 函数遍历每个从通道接收到的数据,因为 c 在发送完 10 个_
  4. _// 数据之后就关闭了通道,所以这里我们 range 函数在接收到 10 个数据_
  5. _// 之后就结束了。如果上面的 c 通道不关闭,那么 range 函数就不_
  6. _// 会结束,从而在接收第 11 个数据的时候就阻塞了。_
  7. **for** i <font style="color:#339933;">:=</font> **range** c <font style="color:#339933;">{</font>
  8. fmt<font style="color:#339933;">.</font>Println<font style="color:#339933;">(</font>i<font style="color:#339933;">)</font>
  9. <font style="color:#339933;">}</font>
}

简单实例:

func main() {

c := make(chan string, 2)

c <- “a”
c <- “b”
close(c) //结束通道
for i := range c{

  1. <font style="color:#afbf7e;">fmt</font>.<font style="color:#b09d79;">Println</font>(i)

}

}

go操作数据库

安装:

  1. go get github.com/go-sql-driver/mysql
  2. go get github.com/jmoiron/sqlx