1、
需求:开发 hello.go 程序, 可以输出 hello world by go // 了解 go 的基本结构
开发的步骤:
[1] 目录结构的处理
package main // 表明 hello.go 所在的包是 main 包
import "fmt" // 导入打印函数 Println 需要的 fmt 包
func main() {
fmt.Println("hello world by go")
}
// 在 go 中每一个文件都必须归属于一个包, 不能单独存在
// func 关键字表示 后面是一个函数
// main 是函数名, 是一个主函数,代表程序的入口
// 运行方法:
// 1、命令行用 go build 对go文件编译,运行可执行文件
// 2、直接 go run hello.go 类似于执行一个脚本
PS D:\proj\goproj\src\go_code\project01\main> go run .\hello.go
hello world by go
PS D:\proj\goproj\src\go_code\project01\main> go build .\hello.go
PS D:\proj\goproj\src\go_code\project01\main> ls
目录: D:\proj\goproj\src\go_code\project01\main
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2021/6/22 23:24 2095616 hello.exe // 要变大很多,接近 2 MB
-a---- 2021/6/22 23:20 259 hello.go
PS D:\proj\goproj\src\go_code\project01\main> .\hello.exe
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)
PS D:\proj\goproj\src\go_code\project01\main> go build -o main.exe
PS D:\proj\goproj\src\go_code\project01\main> ls
目录: D:\proj\goproj\src\go_code\project01\main
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2021/6/22 23:24 2095616 hello.exe
-a---- 2021/6/22 23:20 259 hello.go
-a---- 2021/6/22 23:49 2095616 main.exe
PS D:\proj\goproj\src\go_code\project01\main> .\main.exe
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() // 编译不通过 { }
```go
// 定义一个变量或导入包没有使用, 就会编译不通过
package main
import "fmt"
func main(){
var a int = 10
}
Go 语言转义字符:
即 escape char
:
- \t 一个制表符,实现对其功能
- \n 换行
- \ 一个\ 比如路径输出,由于不知道\是不是路径,所以需要\,第一个\转义,打印一个\
- \” 一个””
- \r 一个回车 从当前行的最前面开始输出, 并覆盖掉以前内容
fmt.Println(“天龙八部雪山飞狐\r张飞
“)
输出:张飞
八部雪山飞狐
Practice01:
使用一句输出语句 实现
姓名 年龄 籍贯 住址
zhang 20 河南 郑州
// 转义字符练习
package main
import "fmt"
func main() {
fmt.Println("姓名\t年龄\t籍贯\t住址\nzhang\t20\t河南\t郑州")
}
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
- 切换到其他盘 // `目的盘符:`
```go
C:\Users\34348>e:
系统找不到指定的驱动器。
C:\Users\34348>d:
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
- 复制 或 移动文件
- copy .\abc.txt ..\ 也可以重命名 copy .\abc.txt ..\a.txt
- 移动是 move 命令
- 删除文件
- `del abc.txt`
- 清理屏幕
- `cls` // 苍老师
- 推出 docs
- `exit `
**_Practice02:_**<br />切换到 d 盘,新建一个目录,切换到该目录新建 a b c 三个目录,然后切换到 a 新建文件 he.txt 复制到 b下并追加内容 dddd ,最后都删除
```go
Microsoft Windows [版本 10.0.19042.1052]
(c) Microsoft Corporation。保留所有权利。
C:\Users\34348>d:
D:\>md zhang
D:\>cd zhang
D:\zhang>md a b c
D:\zhang>
D:\zhang>cd a
D:\zhang\a>echo > he.txt
D:\zhang\a>copy .\he.txt ..\b
已复制 1 个文件。
D:\zhang\a>cd ..\b
D:\zhang\b>echo dddd > he.txt
D:\zhang\b>cd ..
D:\zhang>cd ..
D:\>rd /q/s .\zhang
变量:variable
变量是程序的基本组成单位
- 变量相当于内存memory中的一个数据存储空间的表示,可以把变量看做是一个房间的门牌号,通过门牌号可以找到房间,同样的通过变量名可以访问到内存中的变量值
基本使用
- 1、声明/定义
- 2、赋值
- 3、使用
package main
import "fmt"
func main() {
var a int // 1、定义变量, 用关键字 var ,var 变量名 变量类型
a = 100 // 2、变量赋值
fmt.Println(a) //3、使用变量
}
golang 变量使用三种方式:
1、指定变量类型,声明后如果不赋值 则 使用默认值
int(0) bool(false) string(“”)
2、根据值的类型自动推到变量类型 ( 类型推导 )var num = 100.10
// 自动推导 为 float64
3、省略 var 关键字 // 注意左侧的变量不能是已经声明过的name := "zh"
// 等价于 var name string = “zh”
4、多变量声明
var n1, n2, n3 int
fmt.Println(n1, n2, n3) // 0 0 0
var n1,name,n3 = 100,"zh",888 //同时定义不同类型的多个变量
// 同样可以使用类型推导
n1,name,n3 := 100, "zh", 9000
全局变量:
在 go 语言中,在 go 函数外部定义的变量就是 全局变量 global variable
// method 1
-----------------------------------
package main
import "fmt"
var n1 = 100
var n2 = 200
var name = "zhang"
func main(){
fmt.Println(n1,n2,name)
}
-----------------------------------
// method 2 简洁写法
-----------------------------------
package main
import "fmt"
var (
n1 = 100 // 1、小括号 () 2、变量之间不用 , 分隔开
n2 = 200
nam3 = "zhang"
)
func main(){
fmt.Println(n1,n2,name)
}
-----------------------------------
变量使用细节:
- 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)
// 查看程序中的某个变量的占用字节大小和 数据类型 ( 使用较多 )
var n2 int64 = 10
// 用到 unsafe 包里的 Sizeof 函数
fmt.Printf("n2的数据类型是 %T,n2的占用字节数是 %d",n2,unsafe.Sizeof(n2))
// 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
// 尾数部分可能丢失
浮点型使用细节:
- golang 的浮点类型有 固定的范围和字段长度, 不受 os(操作系统) 的影响
- golang 的浮点类型默认声明为 float64
浮点型常量的 2 种表示方式:<br />十进制数形式:如 5.12 .512 ( 必须有小数点 ) //表示 0.512<br />科学计数法形式:如 5.1234e2 = 5.1234 * 10^2 // e 和 E 效果一样<br />5.12E-2 = 5.12/(10^2)
[ 字符类型 char ]<br />golang 没有专门的 字符类型
- 如果保存单个字符( 字母 ), 一般用 byte 保存( 0~255 )
字符串:传统是由一串固定长度的字符 连接起来的 字符序列 ( 字符组成 )<br />但是<br />`go 语言的字符串是由 单个字节连接组成的`。
```go
// 字符demo
var c1 byte = 'a'
var c2 = '0' //字符的 0
fmt.Println("c1=",c1)
fmt.Println("c2=",c2)
// 输出
//c1= 97
//c2= 48
// 当直接输出 byte 类型时就是输出对应的字母的 ascii 码值 a=>97
// 如果要输出对应的字符, 需要使用 Printf 进行格式化输出
fmt.Printf("c1=%c,c2=%c\n",c1,c2)
// 输出 c1=a,c2=0
// 关于汉字
//var c3 byte = '北' // 看汉字对应的码值是否在 byte 存储范围内
// 汉字是 unicode 类型 , 用 byte 存储会溢出
var c3 int16 = '北'
fmt.Printf("c3=%c,c3对应的码值=%d\r\n",c3, c3)
// 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 字符
var c4 int16 = 23455
fmt.Printf("c4=%c,c4的码值=%d",c4,c4)
// 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 文本
// string 简介
var address string = "北京长城 110 hello"
fmt.Printf("%v",address) // %s 占位符也可以
// 输出: 北京长城 110 hello
字符串使用细节:
1、go 语言的字符串的 字节使用 utf-8 编码标识的 unicode 文本,、
这样 go 同一使用了 utf-8 编码, 避免了中文乱码问题
2、go 中的 字符串一旦被赋值了, 就不能对其字符进行修改 [ 即 go 中字符串是不可变的 ]
var name = "zh"
//name[0] = 'a' 错误语法: Cannot assign to name[0]
3、golang 中字符串表示形式 2 种
(1) 双引号 ,会识别转义字符 // var a string = “北京 \n 110 world”
(2) 反引号,以字符串的原生形式输出, 包括换行 和 特殊字符
var name string = "北京 \n 110 world"
fmt.Println(name)
//北京
//110 world
// 如果要输出源代码 比如 "abc\nabc" 不转义的话就会换行输出
// 用到 反引号
var nn string = `abc\nabc`
fmt.Println(nn)
// 输出: abc\nabc
4、字符串的拼接方式
var str string = “hello” + “world”
str += “hshs”
- 当一个拼接的操作很长时, 可以分行写
var str2 = "hello" + "world" + // 注意换行的话一定要把 + 留在上面
"test" + "tt" +
"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=truevar 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
(){}
// 如果变量名、函数名、常量名首字母大写, 则可以被其他包访问到 (首字母大写公有
)
如果首字母小写, 则只能在本包内访问 (首字母小写私有
)
// 引入本地包的目录路径从 当前工作目录开始写
[ 系统保留关键字 ]
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 | 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
}
]
}