zoukankan      html  css  js  c++  java
  • The "Go" Learning Trip -- 2. Go Basics -- Part2

      基本数据类型和操作符

    1. 文件名&关键字&标识符

      1) 所有go源码以.go结尾

      2) 标识符以字母下划线开头,大小写敏感,比如:

      3) _是特殊标识符,用来忽略结果

      4) 保留关键字

      

      

    2. Go程序基本结构

    •   任何一个代码文件隶属于一个包
    •   import 关键字,引用其他包:

    • golang可执行程序,package main,并且有且只有一个main入口函数
    • 包中函数调用:
    1. 同一个包中函数,直接调用
    2. 不同包中函数,通过包名+点+函数名进行调用
    •   包访问控制规则:
    1. 大写意味着这个函数/变量是可导出的
    2. 小写意味着这个函数/变量是私有的,包外部不能访问

    # exercise time -- exercise 1

        

     思路: 需要一个迭代,迭代的变量进行递减,并用格式化输出

    # 代码如下

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func calcValue(n int) {
     8     for item := 0; item <= n; item++ {
     9         fmt.Printf("%d + %d = %d
    ", item, n-item, n)
    10     }
    11 }
    12 func main() {
    13     calcValue(10)
    14 }
    View Code

    # exercise time -- exercise 2

     

    # 比较简单直接上码

     1 //  新建一个main目录下的mainDemo.go
     2 package main
     3 
     4 import (
     5     "fmt"
     6     "go_dev/day2/example1/add"
     7 )
     8 
     9 func main() {
    10     fmt.Println(add.Name)
    11     fmt.Println(add.Age)  //这里注意如果用小写的变量名,将提示不可引用
    12 }
    13 
    14 // 新建一个add目录下的addPkg.go
    15 package add
    16 
    17 // Name is Author
    18 var Name = "Loki"
    19 
    20 // Age is Author's age
    21 var Age = 16
    View Code

    # exercise time -- exercise 3

     

    # 比较简单 X 2 直接上码

     1 // 新建目录main下面的mainDemo.go
     2 package main
     3 
     4 import (
     5     "fmt"
     6     lokiPkg "go_dev/day2/example3/add" // 这里定义别名
     7 )
     8 
     9 func main() {
    10     fmt.Println("result: ", lokiPkg.Name) //这里调用别名
    11     fmt.Println("result: ", lokiPkg.Age)
    12 }
    13 
    14 // 新建目录add下面的addDemo.go
    15 package add
    16 
    17 var Name string = "Loki"
    18 var Age int = 16
    View Code

    # exercise time -- exercise 4

     

     # 关于 init() 函数 会优先执行

    执行顺序:  先初始化全局变量 --> 调用初始化函数init() -->  执行main()函数

     1 //main目录下的mainDemo.go
     2 package main
     3 
     4 import (
     5     "fmt"                      //lokiPkg "go_dev/day2/example3/add" // 这里定义别名
     6     "go_dev/day2/example3/add" // 这里定义别名
     7 )
     8 
     9 func main() {
    10     fmt.Println("result: ", add.Name) //这里调用别名
    11     fmt.Println("result: ", add.Age)
    12 }
    13 
    14 
    15 //add目录下的addDemo.go
    16 package add
    17 
    18 import (
    19     "fmt"
    20 )
    21 
    22 // Name just Master's name
    23 var Name string = "Loki"
    24 
    25 // Age just Master's age
    26 var Age int = 16
    27 
    28 // init code will execute first
    29 func init() { //Note! here "init" is lower case
    30     fmt.Println("Welcome back! Master")
    31 
    32 }
    View Code

     # exercise time -- exercise 5

    # 包的初始化,不引用。  如果仅仅是想导入包,但是不小调用包的内容可以在包名前面加一个"_"

    PS:多层导入,会以最里面(最深入的一层)的导入的init() 函数开始执行

     1 package main
     2 
     3 import (
     4     _ "go_dev/day2/example3/add" // 注意这里,导入了包,包名位置有个"_"
     5 )
     6 
     7 func main() {
     8     // fmt.Println("result: ", add.Name) //这里取消了调用
     9     // fmt.Println("result: ", add.Age)
    10 }
    View Code

    函数声明和注释

    1. 函数声明:

    格式:  func 函数名字(参数列表)(返回值列表){}

      

    无返回值

    有参数,有返回值

    有参数,有多个返回值

     2. 注释,两种注释,单行注释: //  和多行注释/* */

     

     3. 常量和变量

    •   常量使用const 修饰, 代表永远是只读的,不能修改。
    •   const 只能修饰boolean number(int相关类型、浮点型、complex)和string
    •   语法: const identifier  [TYPE] = value,其中type可以省去

     

     # exercise time -- exercise 6

     

    # 常量实验

    毫秒: Millisecond

    微秒: Microsecond 

     1 package main
     2 
     3 import (
     4     "fmt"
     5     "time"
     6 )
     7 
     8 const (
     9     Male   = 1
    10     Female = 2
    11 )
    12 
    13 func main() {
    14     for {
    15         if sec := time.Now().Unix(); sec%Female == 0 {
    16             fmt.Print("Female")
    17         } else {
    18             fmt.Println("Man")
    19         }
    20         time.Sleep(time.Second)  //防止死循环执行太快耗尽CPU
    21     }
    22 }
    View Code

     # iota

    iota是golang语言的常量计数器,只能在常量的表达式中使用。iota在const关键字出现时将被重置为0(const内部的第一行之前),const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。使用iota能简化定义,在定义枚举时很有用。

     # 写个例子

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main() {
     8     const (
     9         _ = iota // 丢弃第一个数字"0"
    10         a
    11         b
    12         c
    13     )
    14     fmt.Println(a, b, c)
    15 
    16 }
    View Code

    # 变量

    语法: var identifier type

     

    PS: GO语言里面可以做类型推导 

     # exercise time -- exercise 7 

     

     Tips: 相当于是个获取CMD设置的%变量名% 的东东(os.Getenv)

    # 所以,可以这样玩,举个例子

     1 package main
     2 
     3 import (
     4     "fmt"
     5     "os"
     6 )
     7 
     8 func main() {
     9         // 变量的常规写法
    10     var goos string = os.Getenv("OS")
    11         // 变量的偷懒写法,Getenv里面的值就是cmd里面的%变量%
    12     path := os.Getenv("PATH")
    13     goPath := os.Getenv("GOPATH")
    14     goRoot := os.Getenv("GOROOT")
    15     fmt.Printf("The OS is : %s
    ", goos)
    16     fmt.Printf("The GO Path is : %s
    ", goPath)
    17     fmt.Printf("The GO Root is : %s
    ", goRoot)
    18     fmt.Printf("The OS Path is : %s
    ", path)
    19 
    20 }
    View Code

     

     值类型和引用类型

    32位系统指针是4个字节

    64位系统指针是8个字节

    值类型:基本数据类型int 、float、bool、string以及数组和struct(结构体).

    引用类型:指针、slice(切片)、map、chan等都是引用类型

      # exercise time -- exercise 8 

     

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main() {
     8     a := 100                           //值类型
     9     // 可以简写为 b := make(chain int,1)
    10     var b chan int = make(chan int, 1) //引用类型
    11     fmt.Println("a=", a)
    12     fmt.Println("b=", b)
    13 
    14 }
    View Code

    # 输出结果截图

    # 附加演示有“游标”和无游标对函数调用以后对变量的影响

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 // Noncursor is 非定义游标的方式
     8 func Noncursor(n int) {
     9     n = 10
    10 }
    11 
    12 // Cursor is 定义使用游标的方式
    13 func Cursor(n1 *int) {
    14     *n1 = 11
    15 }
    16 
    17 func main() {
    18     n := 99
    19     n1 := 99
    20     a := 100                           //值类型
    21     var b chan int = make(chan int, 1) //引用类型
    22     fmt.Println("a=", a)
    23     fmt.Println("b=", b)
    24     Noncursor(n)
    25     fmt.Println("n=", n) // 结果还是为99 没有变化
    26     Cursor(&n1)
    27     fmt.Println("n1=", n1) //结果为11 已经修改
    28 
    29 }
    View Code

     PS: 堆 & 栈的区别

    栈 先进后出    占空间去分配                   <--- 值类型

    堆 先进先出     系统的内存堆分配           <---  引用类型

     栈大小 C语言 几m    Go语言几k

    堆内存性能没有栈内存高

      # exercise time -- exercise 9 

     

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 // ChangeWay1 is change x and y value
     8 func ChangeWay1(x, y int) (int, int) {
     9     fmt.Println("Myself Way1---↓ Success")
    10     x1, y1 := y, x
    11     return x1, y1
    12 }
    13 
    14 // ChangeWay2 is change x and y value, --> Error Demo!!! <--
    15 func ChangeWay2(x, y int) {
    16     fmt.Println("Error Way2---↓ Fail")
    17     tmp := x
    18     x = y
    19     y = tmp
    20     return
    21 }
    22 
    23 // ChangeWay3 is change x and y value, 采用了修改游标方式,直接修改了地址
    24 func ChangeWay3(x, y *int) {
    25     fmt.Println("Right Way3---↓ Sucess")
    26     tmp := *x
    27     *x = *y
    28     *y = tmp
    29     return
    30 }
    31 
    32 // ChangeWay4 is change x and y value
    33 func ChangeWay4(x, y int) (int, int) {
    34     fmt.Println("Myself Way4---↓ Success")
    35     return y, x
    36 }
    37 
    38 func main() {
    39     x := 3
    40     y := 4
    41     fmt.Println(ChangeWay1(x, y))
    42     ChangeWay2(5, 6)
    43     fmt.Println(x, y)
    44     fmt.Println(ChangeWay4(x, y)) // 注意这里方法3之所以要放到方法4下面,是因为方法3修改了地址指向内容,会导致地址指向的值产生变化
    45     x, y = y, x  // 这里值已经被修改
    46     fmt.Println("Myself Way5---↓ Success", x, y)
    47     ChangeWay3(&x, &y)
    48     fmt.Println(x, y)  // 这里再次做了一个交换,所以值又变了回去
    49 
    50 }
    View Code

    # 执行结果

     变量的作用域

    1. 在函数内部声明的变量叫做局部变量,声明周期仅限于函数内部。

    2. 在函数外部声明的变量叫做全局变量,生命周期作用于整个包,如果是大写的,则作用于整个程序(小写也是作用于整个程序,只是私有,外部访问不了)

    3. 在函数内部语句块声明的变量仅在语句块中生效,语句块外不起作用

    # 语句块 是被"{ }"里面的语句,例如:

    func test(){    //局部变量
    
        for i :=0; i < 100; i++{   //语句块
    
        var b = i * 2      
    
        }
    
    }

       # exercise time -- exercise 10

     

     # 测试结果

        # exercise time -- exercise 11

     

      # 测试结果

     

        # exercise time -- exercise 12

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 var a string
     8 
     9 func main() {
    10     a = "G"
    11     print(a)
    12     f1()
    13 
    14 }
    15 
    16 func f1() {
    17     a := "O"
    18     fmt.Println(a)
    19     f2()
    20 }
    21 
    22 func f2() {
    23     fmt.Println(a)
    24 }
    View Code

    # 执行结果

     

      

    4. 数据类型和操作符

    bool类型,只能存true和false

      2)相关操作符, !、&&、||

    &&特性--> 短路操作: 前面表达式如果false,就不会去求后面的表达式

    || 特性 --> 前面表达式已经为true,后面的表达式就不用求了

    关于这3个符号的优先级:  !>&&>||.

    # 逻辑与(&&) (有假即假

     # 逻辑或(||)(有真即真

     # 举个例子

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main() {
     8     var a bool = true
     9     var b bool = false
    10     // "&&" 有假即假, "||"有真即真
    11     fmt.Printf(" !a的结果: %t
     !b的结果: %t
     a && b的结果: %t
     a||b的结果: %t
    ", !a, !b, a && b, a || b)
    12 
    13 }
    View Code

    # 执行结果截图

    数字类型,主要有int、int8、int16、int32、int64、uint8、uint16、uint32、uint64、float32、float64

     PS: uint = 无符号整型; 有符号和无符号的区别(+、- 正负)

    8位(1字节)

    类型转换,type(variable),比如:var a int=8; var b int32=int32(a)

         # exercise time -- exercise 13

     

     # 上面输出结果肯定是编译错误,原因见下面代码:

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main() {
     8     var n int16 = 34
     9     var m int32
    10     // m = n   这里没有使用类型转换,编译将报错
    11     m = int32(n) // 这里使用了类型转换,可以正常输出结果
    12     fmt.Printf("m is %d
     n is %d
    ", m, n)
    13 
    14 }
    View Code

    逻辑操作符: == 、!=、<、<=、>和>=

    数学操作符:+、-、*、/等等

    PS: 一个等于符号"=" 是赋值

        # exercise time -- exercise 14

     

     # 10 个显示结果不方便看,改为了3

    # 里面有个 math/rand 的包,有点意思

    # db.Seed(time.Now().UnixNano()) // 初始化随机种子以纳秒方式产生随机(不设置这个将产生重复值)
     1 package main
     2 
     3 import (
     4     "fmt"
     5     db "math/rand"  //设置别名
     6     "time"
     7 )
     8 
     9 // 初始化工作
    10 func init() {
    11     db.Seed(time.Now().UnixNano()) // 让随机种子以纳秒方式产生随机(不设置这个将产生重复值)
    12 
    13 }
    14 
    15 func main() {
    16     // 10个随机整数
    17     for item := 0; item < 3; item++ {
    18         res := db.Int()
    19         fmt.Println(res)
    20     }
    21     // 10 个小于100的随机整数
    22     for item := 0; item < 3; item++ {
    23         res := db.Intn(100)
    24         fmt.Println(res)
    25     }
    26     // 10 个随机浮点数
    27     for item := 0; item < 3; item++ {
    28         res := db.Float32()
    29         fmt.Println(res)
    30     }
    31 
    32 }
    View Code

      

    5. 字符串类型

    字符类型: var a byte

                        var a byte = `c`  (只能使用单引号)

    字符串类型:  var str string

    字符串表示两种方式: 1)双引号 2)`` (反引号

    双引号:

    反引号:源生字符串

     # 双引号和反引号

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main() {
     8     name := "Loki"
     9     // 会保留换行操作动作,字符串原本的格式,换行不需要转义符
    10     var str = `Hello Loki
     
     
     
    11     this is a test string,
    12     This is a test string too.`
    13     fmt.Printf("Hello %s 
    
    ", name) // "" 双引号需要转义符
    14     fmt.Printf(`str2= %s`, str)
    15 }
    View Code

    #  关于byte和单引号不得不说的故事

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main() {
     8     name := "Loki"
     9     luckyLetter := 'L' // 用单引号表示定义一个byte字符
    10     fmt.Printf("My name is %s
    ", name)
    11     fmt.Println(luckyLetter)                         // 发现输出字符是数字?其实是ASCII编码
    12     fmt.Printf("This is letter ->%c<-", luckyLetter) // %c 表示byte,使用格式化输出即可显示正确字母
    13 }
    View Code

    # 详细的官方文档参考

    https://go-zh.org/pkg/fmt/

    # 从int 转换为str 例子:

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main() {
     8     var data int = 100
     9     fmt.Println("value:", data)
    10     fmt.Printf("数据类型是:%T
    ", data)
    11     str := fmt.Sprintf("%d", data) // int to str
    12     fmt.Println("value: ", str)
    13     fmt.Printf("数据额类型是:%T
    ", str)
    14     fmt.Printf("a=%q", str )
    15 
    16 }
    View Code

    # 2种字符串拼接方法

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main() {
     8     str1 := "Loki"
     9     str2 := 16
    10     str3 := fmt.Sprintf("%d", str2)
    11 
    12     way1 := str1 + " " + str3                //  string joint way 1
    13     way2 := fmt.Sprintf("%s %s", str1, str3) // string joint way 2
    14     fmt.Println(way1)
    15     fmt.Println(way2)
    16 
    17 }
    View Code

    # 字符串长度判断len()和切片

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main() {
     8     str1 := "Loki So Cool!"
     9     fmt.Println("string length is : ", len(str1))
    10     fmt.Println(str1[0:3])
    11     fmt.Println(str1[5:7])
    12     fmt.Println(str1[8:])
    13 
    14 }
    View Code

    # 2种方法实现字符串反转功能函数 

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 // reverse is function help string reversal
     8 func reverse(str string) string {
     9     var res string
    10     strLen := len(str)
    11     for i := 0; i < strLen; i++ {
    12         res = res + fmt.Sprintf("%c", str[strLen-i-1])
    13     }
    14     return res
    15 }
    16 
    17 func array(str string) string {
    18     var res []byte    //定义数组
    19     tmp := []byte(str)
    20     strLen := len(str)
    21     for i := 0; i < strLen; i++ {
    22         res = append(res, tmp[strLen-i-1])  // 从末尾到开头一个个字符加入数组
    23     }
    24     // fmt.Println(res)  输出结果默认是数组,所以返回值需要string()一下
    25     return string(res)
    26 }
    27 
    28 func main() {
    29     str1 := "Loki So Cool!"
    30     result := reverse(str1)
    31     fmt.Println("way1 result: ", result)
    32     resultWay2 := array(str1)
    33     fmt.Println("war2 result: ", resultWay2)
    34 }
    View Code

     做题思路:

    1. 搞清楚几个陌生术语,然后进行此题逻辑思考

    素数: 只能被1整和自己整除的数,我们就认为它是素数

    %  运算符 - 模除(取整除后的余数) 

    # 方法1

     1 package main
     2 
     3 import "fmt"
     4 
     5 //  1. 判断 101-200 之间有多少个素数,并输出所有素数。
     6 func isPrime(num int) bool {
     7     if num <= 1 {
     8         return false
     9     }
    10     for i := 2; i < num; i++ {
    11         if num%i == 0 {
    12             return false
    13         }
    14     }
    15     return true
    16 }
    17 
    18 func main() {
    19     count := 0
    20     for x := 101; x < 200; x++ {
    21         res := isPrime(x)
    22         if res {
    23             fmt.Printf("%d is Prime
    ", x)
    24             count++
    25         }
    26     }
    27     fmt.Printf("Total is %d", count)
    28 
    29 }
    View Code

    “水仙花数”

    阶乘

  • 相关阅读:
    elastic-job-lite-console运维平台的部署使用
    elastic-job简单入门
    23种设计模式学习之单例模式
    23种设计模式学习之抽象工厂模式
    23种设计模式学习之静态工厂方法模式
    微信公众号开发之-回调的所有类型
    nginx学习-超详细nginx配置文件
    nginx学习-简介
    23种设计模式学习之一
    linux 下jenkins安装
  • 原文地址:https://www.cnblogs.com/Cong0ks/p/14066056.html
Copyright © 2011-2022 走看看