The "Go" Learning Trip -- 1. Hello Go, Frist “go” Code -- Part1

#  第一段go代码

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func add(a int, b int) int {
 8     var sum int
 9     sum = a + b
10     return sum
11 }
12 
13 func main() {
14     var res int
15     res = add(100, 200)
16     fmt.Println("hello~Go!", "add(100,200)=", res), 
17 
18 }
View Code

输出结果:

golang语言特性

1. 垃圾回收

  a. 内存自动回收,再也不需要开发人员管理内存

  b. 开发人员专注业务实现,降低了心智负担

  c. 只需要new分配内存,不需要释放

2. 天然并发

  a. 从语言层面支持并发,非常简单

  b. goroute,轻量级线程,创建成千上万个goroute成为可能

  c. 基于CSP(Communicating Sequential Process)模型实现

# 一个简单的go并发展示(由2个文件hello.go和test.go组成)

 1 //hello.go 主文件
 2 package main
 3 
 4 import (
 5     // 调用一个Sleep所需的时间模块
 6     "time"
 7 )
 8 
 9 func add(a int, b int) int {
10     var sum int
11     sum = a + b
12     return sum
13 }
14 
15 //循环命令
16 func main() {
17     for i := 0; i < 100; i++ {
18         // 同包下面的函数可以直接使用"go"进行调用
19         go testPrint(i)
20     }
21 
22     //一定要注意大小写字母
23     time.Sleep(time.Second)
24 }
25 
26 
27 //第二个文件test.go 同main()包下
28 package main
29 
30 import (
31     "fmt"
32 )
33 
34 func testGoroute(a int, b int) {
35     sum := a + b
36     fmt.Println(sum)
37 }
38 
39 func testPrint(a int) {
40     fmt.Println(a)
41 }
View Code

输出结果部分截图:(从下面截图可以看出,这里在go下面实现一个并发是非常容易的)

# 死循环拷机代码改造

 1 // hello.go
 2 package main
 3 
 4 import (
 5     "time"
 6 )
 7 
 8 func add(a int, b int) int {
 9     var sum int
10     sum = a + b
11     return sum
12 }
13 
14 //循环命令
15 func main() {
16     for i := 0; i < 100; i++ {
17         // 同包下面的函数可以直接使用"go"进行调用
18         go testPrint(i)
19     }
20         //默认为1秒,下面为10秒(死循环时间)
21     time.Sleep(10 * time.Second)
22 }
23 
24 
25 // test.go
26 package main
27 
28 import (
29     "fmt"
30 )
31 
32 func testGoroute(a int, b int) {
33     sum := a + b
34     fmt.Println(sum)
35 }
36 
37 func testPrint(a int) {
38     // 进行一个空循环(死循环)
39 
40     for {
41     }
42 }
View Code

PS: 此代码会导致CPU占用达到100%,请勿在生产环境上执行。

3. channel

  a. 管道,类似unix/linux中的pipe

  b. 多个goroute之间通过channel进行通信

  c. 支持任何类型

pipe: 变量名

make: 

chan: 管道 ;  (chan <数据类型>, <管道的容量>)

:=   赋值(Go的一种简化代码的方式)

e.g. 未简化版(需要两行)
var loki int
loki = 1

e.g. 简化版(仅需一行,自动匹配数据类型)
loki := 1

<-  把右边的数据放到左边的变量

# 管道使用方法简单演示

 1 //主函数调用的hello.go文件
 2 
 3 package main
 4 
 5 //主函数执行
 6 func main() {
 7     testPipe()
 8 
 9 }
10 
11 //pipe.go 管道代码的文件
12 package main
13 
14 import (
15     "fmt"
16 )
17 
18 func testPipe() {
19     //管道的设定格式
20     pipe := make(chan int, 3)
21     pipe <- 1
22     pipe <- 2
23     pipe <- 3
24 
25     //定义取管道值的变量名
26     var t1 int
27     var t2 int
28     var t3 int
29     //变量取管道数据(遵从先进先出的原则)
30     t1 = <-pipe
31     t2 = <-pipe
32     t3 = <-pipe
33     // 取玩值后再给管道附一个值
34     pipe <- 4
35     fmt.Println("t1=", t1, "t2=", t2, "t3=", t3)
36     fmt.Println("channel length:", len(pipe))
37 }
View Code

输出结果:

PS:超过管道设定的管道容量会产生死锁

NOTE: 除了channel还可以通过"全局变量"来进行不同goroute数据交互,但是不推荐使用。

# Go 下面的格式化工具(帮你对齐代码)

gofmt 

# goroute之间的交互代码演示(全局变量)

缺点: 数量多了,分不清楚

 1 // hello.go 主main执行文件
 2 package main
 3 
 4 import (
 5     "fmt"
 6     "time"
 7 )
 8 
 9 // 定义全局变量
10 var pipe chan int
11 
12 func add(a int, b int) {
13     sum := a + b
14     // 让程序模拟执行了3秒
15     time.Sleep(3 * time.Second)
16     pipe <- sum
17 
18 }
19 func main() {
20         // 创建管道
21     pipe = make(chan int, 1)
22        // 创建goroute
23     go add(166, 500)
24         //创建变量,进行管道传值
25     sum := <-pipe
26     fmt.Println("res=", sum)
27 }
View Code

# goroute之间的交互代码演示(传参方式)

 1 //hello.go 主main文件,传参方式交互
 2 package main
 3 
 4 import (
 5     "fmt"
 6     "time"
 7 )
 8 
 9 // 在这里进行形参定义,c属于形参
10 func add(a int, b int, c chan int) {
11     sum := a + b
12     // 让程序模拟执行了3秒
13     time.Sleep(3 * time.Second)
14     c <- sum
15 
16 }
17 func main() {
18     // 定义非全局变量, 放在main函数下面
19     var pipe chan int
20     pipe = make(chan int, 1)
21     // 在这里进行实参传值
22     go add(166, 500, pipe)
23     sum := <-pipe
24     fmt.Println("res=", sum)
25 }
View Code

上面2个的执行结果一直,表示成功:

4. 多返回值

  a. 一个函数返回多个值

 # 多函数演示

 1 // 主函数 hello.go
 2 package main
 3 
 4 import (
 5     "fmt"
 6 )
 7 
 8 func main() {
 9     res1, res2 := calc(100, 100)
10     fmt.Println("res1_SUM=", res1, "res2_AVERAGE=", res2)
11 }
12 
13 // 多函数返回值 calc.go
14 package main
15 
16 func calc(x int, y int) (int, int) {
17     sum := x + y
18     avg := (x + y) / 2
19     return sum, avg
20 }
View Code

PS: 多函数返回值类似Python,并且如果返回值有无用的值也类似Python可以使用“_”(但注意,这里的"-"是一种语法,仅能赋值不能引用)

5. 包的概念

  a. 和Python一样,把相同功能的代码放到一个目录,称之为包

  b. 包可以被其他包引用

  c. main包是用来生成可执行文件, 每个程序只有一个main包

  d. 包的主要用途是提高代码的可复用性

Go的编码只有UTF-8

Go项目目录路径规划

export GOPATH=X:/project/

 %GOPATH%/src/go_dev/day1/example1/

 %GOPATH%/vender/

 %GOPATH%/pkg/

函数名想要被调用使用首字母“大写”函数名,不想被调用“小写”函数名

 # 正确的使用方法

  ::calc 目录下面的文件

 1 # addition.go 文件
 2 package calc
 3 
 4 // Add is just the sum of x and y
 5 func Add(x int, y int) int {
 6     res := x + y
 7     return res
 8 }
 9 
10 
11 # subtraction.go 文件
12 package calc
13 
14 // Sub is the value of x minus y
15 func Sub(x int, y int) int {
16     res := x - y
17     return res
18 }
View Code

  ::main 目录下面的文件

 1 # start.go 文件
 2 package main
 3 
 4 import (
 5     "fmt"
 6     "go_dev/day1/package_example/calc"
 7 )
 8 
 9 func main() {
10     res := calc.Add(100, 200)
11     res2 := calc.Sub(100, 200)
12     fmt.Println("res-->", res, "res2-->", res2)
13 }
View Code

# 目录结构

# 生成.exe指定目录方式

go build -o <存放目录> <需要编译的go文件路径>

go build -o bin/calc go_dev/day1/package_example/main

# 通过参数的方式传入管道

 # goroute_demo.go

1 package goroute
2 
3 // Add is the sum of x and y to z(channl)
4 func Add(x int, y int, z chan int) {
5     // Pass the result of the sum of X and Y to Z
6     z <- (x + y)
7 }
View Code

# main.go

 1 package main
 2 
 3 import (
 4     "fmt"
 5     "go_dev/day1/goroute_example/goroute"
 6 )
 7 
 8 func main() {
 9     pipe := make(chan int, 1)
10     // 打开额外的一个线程进行计算
11     go goroute.Add(111, 222, pipe)
12     res := <-pipe
13     fmt.Println("result-->: ", res)
14 }
View Code

作业:

HW--0. 去官网教程自学(不用深挖,但是需要全部过一遍)

 发现官网教学有个离线版,顺便研究了下离线版的安装方法,简单说下:

  a. 自己要有Go环境,并且清楚%GOPATH%路径在哪里,这个下面会有3个文件夹,分别是src,bin,pkg

  b. 去github网站上download 离线版的tour的zip包

  c. 放入%GOPATH% 下面 srcgithub.comGo-zh our(PS:这里还需要解决依赖问题,不过我是用梯子解决的https_proxy=socks5://127.0.0.1:10808)

  d. 执行go install

  e. 会在%GOPATH% 的bin目录中生产一个tour.exe 

  f. 执行即可

 # 看教程领悟小技巧

1. 当连续两个或多个函数的已命名形参类型相同时,除最后一个类型以外,其它都可以省略。

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 // func add(x int, y int) int { 这里原本写法,改用下面简写方式
 8 func add(x, y int) int {
 9     return x + y
10 }
11 
12 func main() {
13     res := add(1, 2)
14     fmt.Println("Add result is : ", res)
15 }
View Code

2. 基本类型

bool  布尔型

string  字符串

int int8 int16 int32 int64  整形
uint uint8 uint16 uint32 uint64 uintptr  无符号整型

byte // uint8 的别名

rune // int32 的别名
// 表示一个 Unicode 码点

float32 float64  浮点型

complex64 complex128

3. 零值

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

零值是:

数值类型为 0,
布尔类型为 false,
字符串为 ""(空字符串)。

 4. 常量  const

常量的声明与变量类似,只不过是使用 const 关键字。

常量可以是字符、字符串、布尔值或数值。

常量不能用 := 语法声明。

# 写个例子呗

package main

import (
    "fmt"
)

const Pi = 3.14

func main() {
    const Word = "世界"
    const Trush = true
    fmt.Println("Hello ", Word)
    fmt.Println("test once...", Trush)

}
View Code

5. for

Go 只有一种循环结构:for 循环。

基本的 for 循环由三部分组成,它们用分号隔开:

初始化语句:在第一次迭代前执行
条件表达式:在每次迭代前求值
后置语句:在每次迭代的结尾执行
初始化语句通常为一句短变量声明,该变量声明仅在 for 语句的作用域中可见。

一旦条件表达式的布尔值为 false,循环迭代就会终止。

注意:和 C、Java、JavaScript 之类的语言不同,Go 的 for 语句后面的三个构成部分外没有小括号, 大括号 { } 则是必须的。

初始化语句和后置语句是可选的。

# 写个例子

 1 # 常规fox 循环格式
 2 package main
 3 
 4 import (
 5     "fmt"
 6 )
 7 
 8 func main() {
 9     sum := 0
10     for item := 0; item < 10; item++ {
11         sum += item
12     }
13     fmt.Println(sum)
14 }
15 
16 # 另外一种版本
17 package main
18 
19 import (
20     "fmt"
21 )
22 
23 func main() {
24     sum := 1
25     for ; sum < 1000; sum++ {
26         sum += sum
27     }
28     fmt.Println(sum)
29 }
View Code

# 把for 当“while”使用

 1 # 此时你可以去掉分号,因为 C 的 while 在 Go 中叫做 for 2 
 3 package main
 4 
 5 import "fmt"
 6 
 7 func main() {
 8     sum := 1
 9     for sum < 1000 {
10         sum += sum
11     }
12     fmt.Println(sum)
13 }
View Code

# 进行一次“死循环”

1 # 如果省略循环条件,该循环就不会结束,因此无限循环可以写得很紧凑。
2 package main
3 
4 func main() {
5     for {
6     }
7 }
View Code

6. if

# e.g.  Go 的 if 语句与 for 循环类似,表达式外无需小括号 ( ) ,而大括号 { } 则是必须的。

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func testFunc(x int) string {
 8     if x > 0 {
 9         // 结果为True 执行这里
10         return "I'm nonZero"
11     }
12     // 结果为Flase执行这里,相当于else
13     return "I'm Zero"
14 }
15 
16 func main() {
17     fmt.Println("result 1: ", testFunc(9), "
", "result 2: ", testFunc(0))
18 
19 }
View Code

# e.g.   if 语句可以在条件表达式前执行一个简单的语句。该语句声明的变量作用域仅在 if 之内。

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func testFunc(x int) string {
 8     // 这里变量v的作用域仅在if里面
 9     if v := 15; x < v {
10         return "Your number is smaller than mine"
11     }
12     if v := 15; x > v {
13         return "your number is bigger than mine"
14     }
15     return "You guessed it"
16 }
17 
18 func main() {
19     fmt.Println(testFunc(15))
20     fmt.Println(testFunc(1))
21     fmt.Println(testFunc(20))
22 
23 }
View Code

7. if 和 else

# e.g. 在 if 的简短语句中声明的变量同样可以在任何对应的 else 块中使用。

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func testFunc(x int) (int, string) {
 8     // 这里变量v的作用域在if和else里面
 9     if v := 99; x == v {
10         return v, "is Right!"
11     } else {
12         return v, "than Bigger OR Smaller mine!"
13     }
14     // 这里开始就不能在调用变量v
15     return 0, "Over"
16 }
17 
18 func main() {
19     fmt.Println(testFunc(99))
20     fmt.Println(testFunc(1))
21 
22 }
View Code

 练习:循环与函数  http://192.168.24.175:3999/flowcontrol/8  部分(8/14) 暂停  (2020.11.27)

HW--1. 使用fmt 分别打印字符串、二进制、十进制、十六进制、浮点数

思路:

官方文档去寻找答案

https://golang.org/pkg/fmt/

# 整形的一些格式介绍

 # 浮点数相关介绍

# 最终作业

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func main() {
 8     str, bin, dec, hex, flo := "Loki", 10, 10, 10, 10.00
 9     fmt.Printf("string-->: %v
", str)
10     fmt.Printf("binary-->: %b
 ", bin)
11     fmt.Printf("decimal-->: %d
", dec)
12     fmt.Printf("hexadecimal-->: %x
", hex)
13     fmt.Printf("float-->: %.2f
", flo)
14 
15 }
View Code

# 输出结果,如下

 

Go 语言之旅

原文地址:https://www.cnblogs.com/Cong0ks/p/14028725.html