zoukankan      html  css  js  c++  java
  • 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 语言之旅

  • 相关阅读:
    编译gcc报错make[3]: Leaving directory `/usr/local/src/gcc-7.4.0/build/gcc' make[2]: *** [all-stage1-gcc] Error 2 处理
    ERROR 1176 (42000): Key 'XXX' doesn't exist in table 'XXX'报错处理
    /lib64/libc.so.6: version `GLIBC_2.18' not found报错解决
    Centos7上pkg-config的安装
    ERROR: Error in Log_event::read_log_event(): 'Found invalid event in binary log', data_len: 31, event_type: 35报错处理
    MySQL5.7主从复制slave报Last_Errno: 1146错误解决
    详述 hosts 文件的作用及修改 hosts 文件的方法
    Java Decompiler(Java反编译工具)
    使用Charles代理工具导致电脑无法正常访问网站(您的连接不是私密连接)
    阿里云服务器Svn-Server无法连接,阿里云服务器SVNServer配置
  • 原文地址:https://www.cnblogs.com/Cong0ks/p/14028725.html
Copyright © 2011-2022 走看看