1、
    需求:开发 hello.go 程序, 可以输出 hello world by go // 了解 go 的基本结构
    开发的步骤:
    [1] 目录结构的处理
    image.png

    1. package main // 表明 hello.go 所在的包是 main 包
    2. import "fmt" // 导入打印函数 Println 需要的 fmt 包
    3. func main() {
    4. fmt.Println("hello world by go")
    5. }
    6. // 在 go 中每一个文件都必须归属于一个包, 不能单独存在
    7. // func 关键字表示 后面是一个函数
    8. // main 是函数名, 是一个主函数,代表程序的入口
    9. // 运行方法:
    10. // 1、命令行用 go build 对go文件编译,运行可执行文件
    11. // 2、直接 go run hello.go 类似于执行一个脚本
    1. PS D:\proj\goproj\src\go_code\project01\main> go run .\hello.go
    2. hello world by go
    3. PS D:\proj\goproj\src\go_code\project01\main> go build .\hello.go
    4. PS D:\proj\goproj\src\go_code\project01\main> ls
    5. 目录: D:\proj\goproj\src\go_code\project01\main
    6. Mode LastWriteTime Length Name
    7. ---- ------------- ------ ----
    8. -a---- 2021/6/22 23:24 2095616 hello.exe // 要变大很多,接近 2 MB
    9. -a---- 2021/6/22 23:20 259 hello.go
    10. PS D:\proj\goproj\src\go_code\project01\main> .\hello.exe
    11. hello world by go

    go build 之后运行二进制文件 和 直接 go run 解释执行两种代码运行方式的区别 ?

    • 1、如果先编译生成了可执行文件, 那么可以将该可执行文件拷贝到没有 go 开发环境的机器上仍然可以运行
    • 2、如果是 go run 运行go的源代码, 那么如果要在另外一个机器上运行则也必须有 go开发环境,否则无法执行
    • 3、编译时,编译器会将程序运行依赖的库文件包含在可执行文件中
      • 所以可执行文件要 变大很多

    go 程序编译说明:
    1、有了 go源文件,通过编译器可以将其编译成机器可以识别的 二进制文件
    2、在该源文件目录下
    通过 go build 命令对 hello.go 文件进行编译. 默认生成的是 文件名前缀的可执行文件 hello.exe
    可以指定编译生成的可执行文件名 ( windows 下是 xxx.exe)

    1. PS D:\proj\goproj\src\go_code\project01\main> go build -o main.exe
    2. PS D:\proj\goproj\src\go_code\project01\main> ls
    3. 目录: D:\proj\goproj\src\go_code\project01\main
    4. Mode LastWriteTime Length Name
    5. ---- ------------- ------ ----
    6. -a---- 2021/6/22 23:24 2095616 hello.exe
    7. -a---- 2021/6/22 23:20 259 hello.go
    8. -a---- 2021/6/22 23:49 2095616 main.exe
    9. PS D:\proj\goproj\src\go_code\project01\main> .\main.exe
    10. hello world by go

    Go 程序开发的注意事项:

    • 1、Go 源文件以 xxx.go 为拓展名
    • 2、Go 应用程序的执行入口是 main 函数
    • 3、Go 语言严格区分大小写 [涉及可见性]
    • 4、Go 每条语句不用加 ;
    • 5、Go 编译器逐行编译, so 不能把多条语句写在 同一行
    • 6、Go 语言定义的变量或者 import 的包如果没有使用到, 编译不通过
    • 7、{ } 的写法具有严格格式要求 ```go func test(){ // 正确 }

    func test() // 编译不通过 { }

    1. ```go
    2. // 定义一个变量或导入包没有使用, 就会编译不通过
    3. package main
    4. import "fmt"
    5. func main(){
    6. var a int = 10
    7. }

    Go 语言转义字符:
    escape char

    • \t 一个制表符,实现对其功能
    • \n 换行
    • \ 一个\ 比如路径输出,由于不知道\是不是路径,所以需要\,第一个\转义,打印一个\
    • \” 一个””
    • \r 一个回车 从当前行的最前面开始输出, 并覆盖掉以前内容

    fmt.Println(“天龙八部雪山飞狐\r张飞“)
    输出:
    张飞八部雪山飞狐

    Practice01:
    使用一句输出语句 实现
    姓名 年龄 籍贯 住址
    zhang 20 河南 郑州

    1. // 转义字符练习
    2. package main
    3. import "fmt"
    4. func main() {
    5. fmt.Println("姓名\t年龄\t籍贯\t住址\nzhang\t20\t河南\t郑州")
    6. }

    image.png


    go语言的注释
    comment

    • 用于注解说明解释程序的文字就是注释 // 提高代码的可读性
    • go 语言的代码注释
      • 行注释 //
      • 块注释 / /

    规范的代码风格:

    • 建议采用行注释
    • 正确缩进 和 留白

    格式化文件
    gofmt -w xxx.go

    • 运算符两边习惯都加空格 // var num int = 2 + 4 * 5
    • 行长约定:
      • 一行 <= 80个字符,超过部分换行展示, 尽量保持 格式优雅

    // 可以参考 golang官方编程指南

    golang 语言标准库 API:
    golang 中文网在线标准库 文档:
    https://studygolang.com/pkgdoc

    API:应用编程接口

    docs 常用命令介绍:
    即 windows 命令行:
    docs 基本介绍:

    • disk operating system 简单说就是 windows 的目录结构

    操作指令:

    终端 —-> docs操作系统 —-> windows的目录
    docs 操作系统解析指令并操作目录结构

    • 新建文件夹
      • D:\>md test 就在 d 盘下创建了 test 文件夹
    • 切换目录
      • cd d:\test100 // windows 下的路径分隔符是 \ 和linux相反
    • 查看当前目录 dir ```go D:>cd Env

    D:\Env>dir 驱动器 D 中的卷是 Data 卷的序列号是 B823-FA8B

    D:\Env 的目录 2021/06/22 19:10

    . 2021/06/22 19:10 .. 2021/06/05 10:08 android 2021/06/22 19:10 c 2021/06/21 14:22 golang 2021/06/22 00:13 gomod 2021/06/05 10:29 java 2021/06/05 11:03 projects 2021/06/06 22:05 tools 0 个文件 0 字节 9 个目录 175,169,458,176 可用字节

    1. - 切换到其他盘 // `目的盘符:`
    2. ```go
    3. C:\Users\34348>e:
    4. 系统找不到指定的驱动器。
    5. C:\Users\34348>d:
    6. D:\Env>
    • 切换到上一级
      • cd ..
    • 切换到根目录
      • cd /
    • 删除目录:
      • rd test // 删除空目录
      • rd /q/s test //q代表不询问,s代表目录下的文件也都删除

    docs 文件操作:

    • 新建 或 追加内容到文件
      • echo hello > d:\test\abc.txt //文件存在就追加, 不存在就创建 ```go d:\Env\tools>echo hello > .\abc.txt

    d:\Env\tools>dir 驱动器 D 中的卷是 Data 卷的序列号是 B823-FA8B

    d:\Env\tools 的目录

    2021/06/23 11:30

    . 2021/06/23 11:30 .. 2021/06/23 11:30 8 abc.txt 2021/06/06 22:05 vscode 2 个文件 29 字节 3 个目录 175,169,458,176 可用字节

    1. - 复制 移动文件
    2. - copy .\abc.txt ..\ 也可以重命名 copy .\abc.txt ..\a.txt
    3. - 移动是 move 命令
    4. - 删除文件
    5. - `del abc.txt`
    6. - 清理屏幕
    7. - `cls` // 苍老师
    8. - 推出 docs
    9. - `exit `
    10. **_Practice02_**<br />切换到 d 盘,新建一个目录,切换到该目录新建 a b c 三个目录,然后切换到 a 新建文件 he.txt 复制到 b下并追加内容 dddd ,最后都删除
    11. ```go
    12. Microsoft Windows [版本 10.0.19042.1052]
    13. (c) Microsoft Corporation。保留所有权利。
    14. C:\Users\34348>d:
    15. D:\>md zhang
    16. D:\>cd zhang
    17. D:\zhang>md a b c
    18. D:\zhang>
    19. D:\zhang>cd a
    20. D:\zhang\a>echo > he.txt
    21. D:\zhang\a>copy .\he.txt ..\b
    22. 已复制 1 个文件。
    23. D:\zhang\a>cd ..\b
    24. D:\zhang\b>echo dddd > he.txt
    25. D:\zhang\b>cd ..
    26. D:\zhang>cd ..
    27. D:\>rd /q/s .\zhang

    变量:
    variable
    变量是程序的基本组成单位

    • 变量相当于内存memory中的一个数据存储空间的表示,可以把变量看做是一个房间的门牌号,通过门牌号可以找到房间,同样的通过变量名可以访问到内存中的变量值

    基本使用

    • 1、声明/定义
    • 2、赋值
    • 3、使用
    1. package main
    2. import "fmt"
    3. func main() {
    4. var a int // 1、定义变量, 用关键字 var ,var 变量名 变量类型
    5. a = 100 // 2、变量赋值
    6. fmt.Println(a) //3、使用变量
    7. }

    golang 变量使用三种方式:
    1、指定变量类型,声明后如果不赋值 则 使用默认值
    int(0) bool(false) string(“”)

    2、根据值的类型自动推到变量类型 ( 类型推导 )
    var num = 100.10 // 自动推导 为 float64
    image.png

    3、省略 var 关键字 // 注意左侧的变量不能是已经声明过的
    name := "zh" // 等价于 var name string = “zh”

    image.png

    4、多变量声明

    1. var n1, n2, n3 int
    2. fmt.Println(n1, n2, n3) // 0 0 0
    3. var n1,name,n3 = 100,"zh",888 //同时定义不同类型的多个变量
    4. // 同样可以使用类型推导
    5. n1,name,n3 := 100, "zh", 9000

    全局变量:
    在 go 语言中,在 go 函数外部定义的变量就是 全局变量 global variable

    1. // method 1
    2. -----------------------------------
    3. package main
    4. import "fmt"
    5. var n1 = 100
    6. var n2 = 200
    7. var name = "zhang"
    8. func main(){
    9. fmt.Println(n1,n2,name)
    10. }
    11. -----------------------------------
    12. // method 2 简洁写法
    13. -----------------------------------
    14. package main
    15. import "fmt"
    16. var (
    17. n1 = 100 // 1、小括号 () 2、变量之间不用 , 分隔开
    18. n2 = 200
    19. nam3 = "zhang"
    20. )
    21. func main(){
    22. fmt.Println(n1,n2,name)
    23. }
    24. -----------------------------------

    变量使用细节:

    • 1、变量表示内存中的一个存储区域
    • 2、该区域有自己的 名称( 变量名 ) 和类型 ( 数据类型 )
    • 3、golang 变量的 3 种使用方式
      • [1] 指定变量类型,声明后不赋值, 使用默认值
      • [2] 根据值 自定判断变量类型 ( 类型推导 )
      • [3] 省略 var, := 左侧的变量不应该是已经声明过的, 否则报错
    • 4、多变量声明
    • 5、该区域的数据值可以在 同一类型范围内不断变化
    • 6、变量在 同一作用域内不能重名
    • 7、变量 = 变量名 + 值 + 数据类型

    数据类型介绍:
    基本数据类型:

    • 数值型
      • 整数: int 、int8、int16、int32、int64、uint、uint8、uint32、uint64、byte
      • 浮点:float32、 float64、
    • 字符型
      • 没有字符型 // 用 byte 来保存单个字母字符。 go 里都是 utf-8 编码, 一个汉字占 3个字符
    • 布尔型 bool
    • 字符串 string

    派生/复杂数据类型:

    • 指针
    • 数组
    • 结构体
    • 管道 channel
    • 函数
    • 切片 slice
    • 接口 interface
    • 集合 map

    [ 整数类型 ]
    就是用来存放整数值的

    类型 有无符号 占用存储空间 表数范围
    int8 1字节 -128 ~ 127 (第一位表示符号,所以2^(8-1))
    int16 2字节 -2^15 ~ 2^15-1
    int32 4字节 -2^31 ~ 2^31 -1
    int64 8字节 -2^63 ~ 2^63 -1

    以 uint8 为例
    0 0 0 0 0 0 0 0 //表示 0
    1 1 1 1 1 1 1 1 //表示 2^8-1 = 255


    要根据表示数的范围 选择 对应的数据类型
    uint8: 0~255

    单纯 int 类型

    • 32bit :占 4 个字节 范围 -2^31 ~ 2^31-1
    • 64bit :占 8 个字节 范围 -2^63 ~ 2^63-1

    uint 类型

    • 32 bit : 4 字节 0 ~ 2^32 -1
    • 64 bit : 8字节 0 ~ 2^64 -1

    rune 类型

    • 与 int32 一样 -2^31 ~ 2^31 - 1
    • 等价 int32, 表示一个 unicode 码, 常用来 表示汉字

    byte 类型

    • 与 uint8 类型一样
    • 0 ~ 255
    • 当要存储 字符类型时选用 byte

    [ 整数类型使用细节 ]

    • 1、golang各整数类型分:
      • 有符号和无符号
      • int 、 uint 、rune、 byte 的大小和系统有关
    • 2、golang 的整数类型默认声明为 int 型
      • 比如 var n1 = 100 // 默认是 int ,64 bit 的就是 int64
    • 3、如何在程序中 查看某个变量的字节大小和数据类型 ?

      • fmt.Printf 用于做格式化输出
      • fmt.Printf("n1 的数据类型是 %T", n1)
        1. // 查看程序中的某个变量的占用字节大小和 数据类型 ( 使用较多 )
        2. var n2 int64 = 10
        3. // 用到 unsafe 包里的 Sizeof 函数
        4. fmt.Printf("n2的数据类型是 %T,n2的占用字节数是 %d",n2,unsafe.Sizeof(n2))
        5. // n2的数据类型是 int64,n2的占用字节数是 8
    • 4、golang 程序中整形变量在使用中, 遵守保小不保大的原则 // 比如年龄基本<=200,int64用不到

      • 即:在保证程序正确运行下,尽量使用占用空间小的数据类型
    • 5、bit:计算机中的 最小存储单位
    • 6、byte:字节,计算机基本存储单元 [ 二进制详说 ]
      • 1 byte = 8 bit

    [ 浮点型/小数类型 ]

    • 就是用来存放小数的 // 比如 1.2 、 0.23、 -1.911

    32bit就是单精度

    • 单精度 float32: 4 字节 -3.403E38 ~ 4.403E38
    • 双精度 float64: 8 字节 -1.798E308 ~ 1.798E308

    关于浮点数在机器中存放的形式:

    • 浮点数 = 符号位 + 指数位 + 尾数位

    即说明 浮点数都是有符号的
    3.56
    表示为:

    • 尾数部分可能丢失, 造成精度损失
      • -123.0000901 ```go // 浮点数精度损失 var num3 float32 = -123.0000901 var num4 float64 = -123.0000901 fmt.Println(“num3=”,num3,”num4=”,num4) // num3= -123.00009 num4= -123.0000901

    // 尾数部分可能丢失

    1. 浮点型使用细节:
    2. - golang 的浮点类型有 固定的范围和字段长度, 不受 os(操作系统) 的影响
    3. - golang 的浮点类型默认声明为 float64
    4. 浮点型常量的 2 种表示方式:<br />十进制数形式:如 5.12 .512 ( 必须有小数点 ) //表示 0.512<br />科学计数法形式:如 5.1234e2 = 5.1234 * 10^2 // e 和 E 效果一样<br />5.12E-2 = 5.12/(10^2)
    5. [ 字符类型 char ]<br />golang 没有专门的 字符类型
    6. - 如果保存单个字符( 字母 ), 一般用 byte 保存( 0~255 )
    7. 字符串:传统是由一串固定长度的字符 连接起来的 字符序列 ( 字符组成 )<br />但是<br />`go 语言的字符串是由 单个字节连接组成的`
    8. ```go
    9. // 字符demo
    10. var c1 byte = 'a'
    11. var c2 = '0' //字符的 0
    12. fmt.Println("c1=",c1)
    13. fmt.Println("c2=",c2)
    14. // 输出
    15. //c1= 97
    16. //c2= 48
    17. // 当直接输出 byte 类型时就是输出对应的字母的 ascii 码值 a=>97
    18. // 如果要输出对应的字符, 需要使用 Printf 进行格式化输出
    19. fmt.Printf("c1=%c,c2=%c\n",c1,c2)
    20. // 输出 c1=a,c2=0
    21. // 关于汉字
    22. //var c3 byte = '北' // 看汉字对应的码值是否在 byte 存储范围内
    23. // 汉字是 unicode 类型 , 用 byte 存储会溢出
    24. var c3 int16 = '北'
    25. fmt.Printf("c3=%c,c3对应的码值=%d\r\n",c3, c3)
    26. // c3=北,c3对应的码值=21271

    说明:

    • 如果 保存的字符在 ASCII 表的,比如 [0-10 ,a-z, A-Z ] 可以直接保存到 byte (0~255范围 )

    • 保存的字符对应码值 > 255 ,考虑用大一点的 int 存储, int16,int32,int64

    字符类型使用注意细节:

    • 1、字符常量使用 单引号 ( ‘ ‘ ) 括起来的单个字符
      • var c1 byte = ‘a’ var c2 int16 = ‘国’ var c3 = ‘10’
    • 2、go 中允许使用 转义字符 “\” 来将其后的字符 转变为 特殊字符型常量
      • 例如: var c4 char = ‘\n’ // 表示换行符
    • 3、 go 语言字符默认使用 utf-8 编码
    • 4、go中 字符的本质是一个 整数 , 直接输出时, 是该字符对应的 ascii 码值

    • 5、可以直接个 某个变量赋值 1个数字,然后按 格式化输出时 %c ,会输出该数字对应的 unicode 字符

      1. var c4 int16 = 23455
      2. fmt.Printf("c4=%c,c4的码值=%d",c4,c4)
      3. // c4=実,c4的码值=23455
    • 6、字符类型可以进行运算。 相当于一个整数, 因为都有对应的 unicode 码值

    • 可以理解为 utf-8 表 包含了 ascii 码表

    7、utf-8 编码格式中 , 英文字母 1 个字节, 汉字 3 个字节

    理解:
    go 语言的编码都统一成了 utf-8, 非常方便统一,再也没有编码乱码的困扰

    [ bool 类型 ]

    • 布尔类型也叫 bool 类型, 只允许取值 true 和 false // 数字不允许, 不能用正数表示为真 // 和 c 语言有区别
    • bool 类型占 1 个字节
    • bool 类型适用于 逻辑运算, 一般用于程序的流程控制 =>
      • if 条件控制语句
      • for 循环控制语句

    [ 字符串类型 ]
    字符串就是一串固定长度的 字符 连接起来的字符序列。
    但是
    go 的字符串是由 单个字节 连接起来的
    go 的字符串的字节使用 utf-8 编码标识的 unicode 文本

    1. // string 简介
    2. var address string = "北京长城 110 hello"
    3. fmt.Printf("%v",address) // %s 占位符也可以
    4. // 输出: 北京长城 110 hello

    字符串使用细节:
    1、go 语言的字符串的 字节使用 utf-8 编码标识的 unicode 文本,、
    这样 go 同一使用了 utf-8 编码, 避免了中文乱码问题
    2、go 中的 字符串一旦被赋值了, 就不能对其字符进行修改 [ 即 go 中字符串是不可变的 ]

    1. var name = "zh"
    2. //name[0] = 'a' 错误语法: Cannot assign to name[0]

    3、golang 中字符串表示形式 2 种
    (1) 双引号 ,会识别转义字符 // var a string = “北京 \n 110 world”
    (2) 反引号,以字符串的原生形式输出, 包括换行 和 特殊字符

    1. var name string = "北京 \n 110 world"
    2. fmt.Println(name)
    3. //北京
    4. //110 world
    5. // 如果要输出源代码 比如 "abc\nabc" 不转义的话就会换行输出
    6. // 用到 反引号
    7. var nn string = `abc\nabc`
    8. fmt.Println(nn)
    9. // 输出: abc\nabc

    4、字符串的拼接方式
    var str string = “hello” + “world”
    str += “hshs”

    • 当一个拼接的操作很长时, 可以分行写
      1. var str2 = "hello" + "world" + // 注意换行的话一定要把 + 留在上面
      2. "test" + "tt" +
      3. "ok" // 因为 go 会在命令最后加 ; 如果一行没有 + 就会添加 ; 导致命令报错

    5、当一行字符串过长时, 需要使用到 多行字符串

    var str2 = "hello" + "world" +  // 注意换行的话一定要把 + 留在上面
    "test" + "tt" +
    "ok"
    

    [ 基本数据类型默认值 ]

    数据类型 默认值
    整形 0
    浮点型 0
    字符型 “”
    布尔类型 false

    [ 基本数据类型相互转换 ]
    golang 和 java 、c 不同
    go 在不同类型的变量之间 赋值时 需要显式转换

    • 也就是说 golang 数据类型不能自动转换

    基本语法:
    %v 格式化输出:表示把变量的值输出

    var i int = 42
    var f float64 = float64(i)
    var u uint8 = uint8(f)
    

    数据转换的细节:

    • 1、go 中的数据类型转换:可以是从表示范围小=>表示范围大, 也可以是 表示范围大=> 表示范围小
    • 2、被转换的是 变量存储的数据(即值), 变量本身的数据类型不发生变化
    • 3、大范围=>小范围, 比如 int64 -> int8 , 编译时不会报错, 只是转换的结果按照 溢出处理
      • 和我们期望的结果不一样

    Practice03:
    判断是否能够通过编译

    // demo1
    func main(){
        var n1 int32 = 12
        var n2 int64
        var n3 int8
    
        n2 = n1 + 20    // x n1是int32 + 12 也会是  int32  编译错误
        n3 = n1 + 20    // 没有类型转换
    }
    
    // demo2
    func main(){
        var n1 int32 = 12
        var n3 int8
        var n4 int8
        n4 = int8(n1) + 127   //int8范围  -128 ~ 127  编译通过,但是会溢出,结果不是139
        n3 = int8(n1) + 128      //这里编译不过,因为系统知道 128 已经查过了 int8的范围,所以加都不会加
        fmt.Println(n3)  // 猜测 127
        // //输出: -117  按溢出处理
    }
    

    如果没有使用到一个包, 但是又不想直接去掉, 前面加 _ 表示暂时先不用

    import (
        _ "fmt"
    )
    

    [ 基本数据类型和string 的转换 ]

    • 常用

    程序开发中,经常需要将 基本数据类型=>转换成 string 类型
    或者将 string类型=> 转换成 基本数据类型
    1、基本类型 转 string
    两种方式

    • [1] 使用fmt.Sprintf("%参数",表达式)

      • 参数 需要和表达式的数据类型 相匹配
      • fmt.Sprintf() 会返回转换后的字符串

        // 普通数据类型 => string method1:  fmt.Sprintf
        var num1 int = 99
        var num2 float64 = 23.456
        var b bool = true
        var mychar byte = 'h'
        var str string  // 默认空的 string 类型
        // 使用  fmt.Sprintf 转化为  string 类型
        str = fmt.Sprintf("%d",num1) //%d 指的是 num1 的数据类型
        // 表示把 num1 转换成 string 类型返回 由 str 变量接收
        fmt.Printf("str type %T str=%v\r\n",str,str)
        //输出: str type string str=99
        
        str = fmt.Sprintf("%f",num2)
        fmt.Printf("str type %T str=%v\r\n",str,str)
        //输出: str type string str=23.456000
        
        str = fmt.Sprintf("%t",b)  //%t 是bool类型的格式化输出
        fmt.Printf("str type %T str=%v\r\n",str,str)
        // %q 输出的字符串带 ""
        //输出: str type string str=true
        fmt.Printf("str type %T str=%q\r\n",str,str)
        //输出: str type string str="true"
        
        str = fmt.Sprintf("%c",mychar)
        fmt.Printf("str type %T str=%q\r\n",str,str)
        //输出: str type string str="h"
        
    • [2] 使用 strconv 包的函数

        // method2 : 使用 strconv 包
        var tt1 int = 99
        var tt2 float64 = 23.456
        var tt3 bool = true
        var str2 string
        str2 = strconv.FormatInt(int64(tt1),10) //第二个参数base表示转换的进制数
        fmt.Printf("str2 type %T str2=%q\r\n",str2,str2)
        //输出: str2 type string str2="99"
        //如果base进制设为2 输出: str2 type string str2="1100011"
      
        // float 参数多点
        str2 = strconv.FormatFloat(tt2,'f',10,64)
        // param2 f代表转成的格式 f: -ddd.dddd   b:-ddddp±ddd 指数为二进制
        // E:-d.ddddE±dd 十进制指数
        // param3 prec表示精度  10 表示小数位保留 10位
        // 64 表示这个数是 float64
        fmt.Printf("str2 type %T str2=%q\r\n",str2,str2)
        //输出: str2 type string str2="23.4560000000"  小数保留 10 位
      
        str2 = strconv.FormatBool(tt3)
        fmt.Printf("str2 type %T str2=%q\r\n",str2,str2)
        //输出: str2 type string str2="true"
      

    还可以用 strconv.itoa(int num) 返回的是一个 string

    func Itoa(i int) string {
        return FormatInt(int64(i), 10)
    }
    

    2、string 转 基本类型

    • [1] 使用 strconv 包的函数 ```go // string => 基本类型 var str3 string = “true” var bbba bool bbba , = strconv.ParseBool(str3) // func ParseBool(str string) (bool, error) 有两个返回值 // 使用 忽略第二个返回值 error fmt.Printf(“bbba type = %T bbba=%v\n”,bbba,bbba) //输出: bbba type = bool bbba=true

      var str4 string = “123456” var n1 int64 n1,_ = strconv.ParseInt(str4,10,0) // func ParseInt(s string, base int, bitSize int) (i int64, err error) // 第二个参数是转换的 进制, 第三个参数代表转换的 int格式 // 0 8 16 32 64 分别代表 int int8 int16 int32 int64 // 返回值是 int64 fmt.Printf(“n1 type = %T n1=%v\n”,n1,n1) //输出: n1 type = int64 n1=123456 // 如果参数3是 8 , 输出: n1 type = int64 n1=127 因为int8只能存储到 127 ,

      var str5 string = “123.456” var f1 float64 f1,_ = strconv.ParseFloat(str5,64) // func ParseFloat(s string, bitSize int) (float64, error) // bitSize 参数表示转换为什么位的 float 为0 默认为 float64

      fmt.Printf(“f1 type = %T f1=%v”,f1,f1) //输出: f1 type = float64 f1=123.456 //如果是 f1,_ = strconv.ParseFloat(str5,32) //输出为: f1 type = float64 f1=123.45600128173828

    //question: 对于 32 的结果 f1=123.45600128173828 不是很理解

    基本数据类型 <=> string 类型 注意事项:<br />1、将 string 类型转成基本数据类型时, **要确保 string类型能够转成有效的数据**。<br />比如可以把 "123" 转成一个整数, 但不能把 "hello" 转成一个整数<br />_如果这样做, golang 直接将其转成 0 [ 重新置为对应类型的默认值 ]_
    
    
    
    [ 指针 ]
    
    - 1、对于基本数据类型,变量存的就是值, **也叫值类型**。
    - 2、获取变量的地址,用 &,比如: var num int  获取num变量的地址  &num
    - 3、指针类型
       - 变量存的是一个地址, 这个地址指向的空间存的才是值
       - 比如: var numindex  *int = &num
    - 4、获取指针类型所指向的值   使用` * `,比如 
       - var num int =1
       - var i = 999
       - var ptr *int = &i
       - *num = 22
    
     <br />指针使用:
    ```go
    // demo1: 写一个程序获取 int 变量num的地址并显示到终端
    // 将num的地址赋给指针 ptr, 并通过 ptr 去修改num的值
    
        // pointer demo
        var numtest int = 10
        fmt.Println("numtest的地址=",&numtest)
        var numpointer *int = &numtest
        *numpointer = 1
        fmt.Println("numtest=",numtest)
        //numtest的地址= 0xc000012128
        //numtest= 1
    

    指针使用细节:

    • 1、值类型都有对应的指针类型,形式为* 数据类型
      • 比如 int 对应的指针 int , float 对应的指针类型是 float
    • 2、值类型包括: 基本数据类型 int 系列 , float 系列, bool,string,数组和结构体 struct

    [ 值类型和引用类型 ]
    值类型包括: 基本数据类型 int 系列 , float 系列, bool,string,数组和结构体 struct
    引用类型:

    • 指针
    • slice 切片
    • map
    • 管道 channel
    • interface 接口

    使用特点:
    如果是值类型, 变量直接存储值, 内存通常在 栈 中分配
    引用类型:变量存储的是一个地址
    这个地址对应的空间才真正的存储数据( 值 ), 内存通常在 堆 上分配
    当没有任何变量引用这个地址时, 该地址对应的数据空间就会成为一个 垃圾, 有 GC 回收

    [ 标识符的使用 ]
    标识符命名:
    go 中对各种变量、方法、函数等命名时使用的字符序列 称为 标识符( 即字符串 )
    凡是自己可以起名字的地方, 都叫 标识符

    命名:
    1、由 26 个英文字母大小写 , 0~9 , 下划线组成
    2、数字不可以开头
    3、golang 严格区分大小写
    4、**
    标识符不能包含空格**
    5、下划线
    在 go 中是一个特殊的标识符, 称为空标识符, 常用来做占位符使用
    6、不能使用系统保留关键字作为标识符, 比如 break, if —-

    包名:
    保持 package 的名字和目录保持一致, // 遵循包名有意义,简短,不和标准库冲突

    变量名,函数名,常量名: 采取 驼峰法 // func GetSum(){}
    // 如果变量名、函数名、常量名首字母大写, 则可以被其他包访问到 (首字母大写公有)
    如果首字母小写, 则只能在本包内访问 (首字母小写私有)

    // 引入本地包的目录路径从 当前工作目录开始写
    image.png

    [ 系统保留关键字 ]
    go 中为了简化代码编译过程中于 代码的解析, 其定义的保留关键字 25

    break default func interface select
    case defer go map struct
    chan else goto package switch
    const fallthrough if range type
    continue for import return var

    除了保留关键字, go 还提供了 36 个预定标识符,
    // 包括基础数据类型 和 系统内嵌函数

    append atoi itoa len make new
    bool int int8 int16 int32 int64
    uint8 uint16 uint32 uint64 float32 float64
    byte string true false complex128 nil
    panic real recover complex complex64 uintprt
    cap len print println close imag

    [ 运算符相关 ]

    • 运算符是一种特殊的符号, 用以表示数据的运算、赋值 和比较

    1、算术运算符

    • 对数值型变量进行运算
    • +-*/(除)、%(取模,余)、++(自增)、--(自减)
    • 10 / 4 = 2 //如果参与运算的数字都是整数, 运算后结果会 去掉小数部分只保留整数部分
    • 不管接收方式类型 var n1 float32 = 10 / 4 // 结果还是 2
    • 10.0 / 4 = 2.5 浮点数参与运算
    • a % b = a - a/b b // -10%3= -10 - (-10)/3 3= -10 -(-9) = -1

    2、赋值运算符

    • 就是将某个 运算后的值 , 再 赋给指定的变量
    • =+=-=*=/=%=、 // 分别对应先进行相关计算之后 再赋值 C+=A <=> C=C+A
    • <<== //左移后赋值 C<<==2 相当于 C= C<<2
    • >>== //右移后赋值
    • &= //按位与后赋值 ^= 按位异或后赋值 |= 按位 或 后赋值

    运算顺序 从右往左, 赋值运算符的左边只能是变量, 右边可以是变量、表达式、常量值


    赋值运算面试题:
    两个变量 a 和 b,交换但是不允许使用中间变量

        // swap but not use temp
        var aa int = 10
        var bb int = 20
        aa = aa + bb    //a=a+b=10+20=30
        bb = aa - bb    //b=a-b=30-20=10
        aa = aa - bb     //a=a-b=30-10=20
        fmt.Println("aa=",aa," bb=",bb)
        //aa= 20  bb= 10
    

    3、比较运算符

    • 关系运算符的结果都是 bool 型, 要么是 true 要么是 false
    • 经常用在 if结构 的条件中 或 循环结构的条件中
    • ==>=!=<=><

    4、逻辑运算符

    • 用于连接多个条件( 一般是关系表达式 ), 最终结果也是一个 bool 值 | && | 逻辑与,两边都为 true 结果为true | true&&true = true | | —- | —- | —- | | || | 逻辑或,两边有一个 true 结果就为 true | true || false = true | | ! | 逻辑非,条件为 true 结果为 false | !true = false | | | &&也叫短路与 第一个条件false,第二个不会判断 | | | | || 也叫短路或,第一个是 true 第二个也不会判断 | |
    func test() bool{
        fmt.Println("test////")
        return true
    }
    func main(){
        shopping.PriceCheck(344)
    
        var i int = 10
        if i<8 && test(){  //test() 返回一个 true
            //无输出, 因为 i<8 是false 不会进行第二个条件判断
            fmt.Println("ok")
        }
    }
    

    5、位运算符

    6、其他运算符
    特殊 & 和 *

    7、三目运算符 ( go 语言没有 三元运算符 )


    算术运算符使用细节:

    • 1、对于除号 “/“ ,它的整数除 和 小数除是有区别的, 整数之间做除法时,只保留整数部分而舍弃小数部分
      • // x := 19/5 结果3
    • 2、取模本质运算 a % b = a - a/b * a
    • 3、go 的自增自减只能当做一个独立的语句 ,不能使用 b:=a++ 这种
    • 4、golang没有 —a 和 ++a, ++ 和 — 只能写在变量之后
    • 5、 if i++ >10 {} 写法错误, i++ 只能单独语句使用

    运算符的优先级:
    只有 单目运算和 赋值运算是 从右向左 运算的

    • 单目:+-!~(type)*&sizeof

    其他都是 从左向右 的

    关于三元运算符:

    var n int
    var i int = 20
    var j int = 12
    
    // 传统的三元运算
    n = i>j ? i:j
    // 如果 i>j 则 n=i, 否则 n=j
    
    // 但是在 golang 中只能用 if else 实现
    if i>j{
        n=i
    }else{
        n=j
    }
    

    demo 案例:

    // demo1: 求出两个数的最大值
    // demo2: 求出三个数的最大值
    
    func getMax2(a,b int)  (ret int ) {
        if a>b{
            return a
        }
        return b
    }
    

    [ 获取用户终端输入 ]
    场景:
    在程序中有时需要接收用户输入的数据, 就可以使用键盘输入语句来获取

    步骤:
    使用 fmt 包的 fmt.Scanln() 或者 fmt.Scanf() 函数

    scanln() 是读取一行的数据

        // test input :
        var name string
        var age byte
        var sal float32
        var ispass bool
        fmt.Println("input name:")
        fmt.Scanln(&name)
    
        fmt.Println("input age:")
        fmt.Scanln(&age)
    
        fmt.Println("input sal:")
        fmt.Scanln(&sal)
    
        fmt.Println("input ispass:")
        fmt.Scanln(&ispass)
    
        fmt.Println(name,age,sal,ispass)
        //input name:
        //zhang
        //input age:
        //12
        //input sal:
        //12333
        //input ispass:
        //true
        //zhang 12 12333 true
    

    // 方式2, 一次性输入 Scanf 可以按指定的格式输入

        // method2: Scanf
        var name string
        var age byte
        var sal float32
        var ispass bool
        fmt.Println("请输入 姓名、年龄、薪水、是否通过考试 || 使用空格隔开")
        fmt.Scanf("%s %d %f %t",&name,&age,&sal,&ispass)
        fmt.Println(name,age,sal,ispass)
        //请输入 姓名、年龄、薪水、是否通过考试 || 使用空格隔开
        //z 19 12222 false
        //z 19 12222 false
    

    vscode 的配置:
    每个 vscode 项目中都有 .launch.json 文件,配置运行代码时的环境,下面是项目中的 .launch.json。

    {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "LaunchGo",
                "type": "go",
                "request": "launch",
                "mode": "auto",
                "remotePath": "",
                "port": 5546,
                "host": "127.0.0.1",
                "program": "${fileDirname}",
                "env": {
                    "GOPATH": "D:/Env/golang/GOPATH",
                    "GOROOT": "D:/Env/golang/Go"
                },
                "args": [],
                //"showLog": true
            }
        ]
    }