Golang学习笔记
0x01程序结构
标识符
Go语言标识符是用于标识变量、函数或任何用户自定义项目的名称。
标识符有两种:
- 用户定义的标识符,作为程序实体。一般来说同一个代码块中,不运行出现同名的程序实体,调用其他包中的实体需要指定包标识符,例如: fmt.Println。
- 预定义标识符,在Go语言源代码中声明,例如数据类型: bool、byte、int; 内建函数名: append、cap、close等。
关键字
关键字也叫保留字,这些保留字不能作为常量、变量或任何其他标识符名称。
Go的关键字相比其他语言来说还算非常少的了,一共只有25个。
- 包导入与声明:import、package。
- 程序实体声明与定义:var、type、func、interface、map、 struct、chan、const。
- 流程控制:if、continue、for、return、go、case、goto、 switch、select、else、break、default、defer、fallthrough、 range。
字面量
通俗的说就是用来表示值的,例如const b int = 10
,这里的b是常量,10为字面量。
分隔符
用于分隔其他元素,例如()
{}
[]
.
,
;
:
......
,程序代码都是通过语句来实现结构化的,但是Go语言不需要以;
结尾,Go语言编译器会自动完成。
运算符
运算符 | 说明 |
---|---|
|| | 或 |
&& | 与 |
! | 非 |
== | 相等判断 |
!= | 不等判断 |
< | 小于判断 |
> | 大于判断 |
<= | 小于等于判断 |
>= | 大于等于判断 |
+ | 求和 |
- | 求差 |
* | 乘积 |
/ | 求商 |
| | 按位或 |
^ | 按位异或 |
% | 求余 |
<< | 按位左移 |
>> | 按位右移 |
& | 按位与 |
&^ | 按位清楚 |
优先级
运算符 | 优先级 |
---|---|
* / % << >> & &^ | 最高 |
+ - | ^ | 较高 |
== != < <= > >= | 中 |
&& | 较低 |
|| | 最低 |
如果出现相同优先级的运算符,则从左到右运算。所有运算符均收到括号的影响。
注释
Go语言可以使用//
单行注释,也可也使用/* */
来多行注释,这与其他大多编程语言并无差异。
常量
常量使用关键字const定义,常量的定义格式为: const 标识符 [类型] = value,例如const Pi float32 = 3.1415926536。这里的类型是可以忽略的,因为Go语言编译器可以判断值的类型。
变量
变量声明的格式是: var 标识符 类型。
例如:
var a int
var b bool
var a,b int
//也可以通过如下方式进行批量定义
var(
a,b int
c bool
str string
)
很有趣的一个点就是,如果想要交换两个变量的值,可以直接使用a,b=b,a
,不再需要使用Temp变量去充当中间商hhhh。
变量的声明不仅可以通过var来定义,还可以直接在使用的时候通过:=
定义并赋值,例如: a := 1。
注意:
:=
方式不能用于全局变量的声明和赋值- 同一个代码块内不能多次声明同一个变量
- 函数体内属于独立代码块,可以再次声明变量a,可 以改变变量的类型,并且定义只在函数内部生效
- 局部变量声明了就必须使用,全局变量可以声明了不被使用
在使用某个函数的时候,往往会出现多个返回值,但我们只需要其中的一个返回值,则可以使用_
占位。
package main
import "fmt"
func main() {
fmt.Println("Who are U?")
Name, Age, _ := GetInfo()//用_匿名变量来接收Hobby的值
fmt.Println("I am " + Name + ",and I am " + Age + "years old")
}
func GetInfo() (Name string, Age string, Hobby string) {
return "Le1aaaaa", "20", "Security"
}
init函数
init函数执行优先级比main函数高,一个源文件只能有一个init函数。
package main
import (
"fmt"
"math"
)
var Pi float64
func init() {
Pi = 4 * math.Atan(1)
}
func main() {
DPi := Pi * Pi
fmt.Println(Pi, DPi)
}
//3.141592653589793 9.869604401089358
0x02基础数据类型
整型
整型的表示
package main
import "fmt"
var value1 int32 //全局声明
func main() {
value2 := 64 //函数内部声明
fmt.Println("value2:" + fmt.Sprint(value2))
}
整型的运算
package main
import "fmt"
func main() {
x, y := 2, 4
if x == y {
fmt.Println("x等于y")
} else {
fmt.Println("x不等于y")
}
}
运算 | 例子 | 结果 |
---|---|---|
x<<y,左移(x乘以2的y次方) | 1<<2 | 4 |
x>>y,右移(x除以2的y次方) | 12>>2 | 3 |
x ^ y,异或 | 1^2 | 3 |
x & y,与 | 1&2 | 0 |
x | y,或 | |2 | 2 |
^x,取反 | ^2 | -3 |
浮点型
浮点型的表示
package main
import (
"fmt"
"reflect"
)
func main() {
var value1 float64
value1 = 1 //不管是否有小数点,value1都是浮点型
value2 := 2 //如果没有小数点,则会被推导为整型
value3 := 3.0 //如果有小数点,value3会被推导为浮点型
// v := value1 + value2 //编译失败,因为类型不同
v := value1 + value3
fmt.Println(value1, value2, value3, v)
fmt.Println("v的类型是: ", reflect.TypeOf(v))
}
浮点数的运算
package main
import "fmt"
func main() {
var value1 float64
value1 = 1
value2 := 1.00000000000000000000001
if value1 == value2 {
fmt.Println("相等")
}
}
//相等,因为精度限制在小数点后15位
字符与字符串
字符串的表示
package main
import "fmt"
var value1 float64
func main() {
s := "aA你2"
fmt.Println("字符串长度:", len(s))
for i := 0; i < len(s); i++ {
fmt.Println(s[i])
}
s = "你好, "
t := s
s += "世界。" //字符串可以连接,但原字符串不会改变
fmt.Println(s)//你好, 世界。
fmt.Println(t)//你好,
}
解释字符串
该类字符串使用""
括起来,其中的相关转义字符将会被替换。
非解释字符串
该类字符串使用反引号括起来,可以跨行,并且会直接把引号内的所有内容直接输出。
package main
import "fmt"
func main() {
str1 := `苟利国家生死以\n
岂因祸福避趋之`
str2 := "今天天气\n真好"
fmt.Println(str1)
fmt.Println(str2)
}
/*苟利国家生死以\n
岂因祸福避趋之
今天天气
真好*/
遍历字符串
第一种方式输出了乱码,原因是使用的len()
方法是不能用来遍历字符串的,因为Go使用UTF-8
来保存字符串,所以每个字符由多个字节组成,只输出其中的一个字节
是无法显示为一个完整字符的。所以需要使用range
方法。
package main
import "fmt"
//遍历字符串
func main() {
s := "我是中国人"
for i := 0; i < len(s); i++ {
fmt.Printf("%c", s[i])
}
fmt.Printf("\n")
for _, v := range s {
fmt.Printf("%c", v)
}
fmt.Println("\n")
}
/*
ææ¯ä¸å½äºº
我是中国人
*/
字符串修改
Go语言字符串不能修改,也就不能使用s[i]
的方法来修改字符串中的UTF-8
编码。但是可以把字符串赋予给新的变量中,一般使用[]byte
或者[]rune
类型。如果修改字节,则转化为[]byte
类型,如果修改字符,则转化为[]rune
类型。
package main
import "fmt"
//修改字符串 byte[]类型
func main() {
s := "Hello 世界!"
b := []byte(s)
b[5] = ','
fmt.Printf("%s\n", s) //s的值不会被修改
fmt.Printf("%s\n", b) //修改后的数据
/*
Hello 世界!
Hello,世界!
*/
}
package main
import "fmt"
//修改字符串 []rune
func main() {
s := "我爱世界"
b := []rune(s)
b[2] = '中'
b[3] = '国'
fmt.Printf("%s\n", s)
fmt.Printf("%s\n", string(b))
/*我爱世界
我爱中国*/
}
strings包
这是一个处理字符串的包
包含判断
package main
import (
"fmt"
"strings"
)
//包含判断
func main() {
a := "I am Le1aaaaa"
fmt.Printf("%t\n", strings.HasPrefix(a, "I")) //判断字符串a 是否以I开头
fmt.Printf("%t\n", strings.HasSuffix(a, "Le1aaaaa")) //判断字符串a 是否以Le1aaaaa结尾
fmt.Printf("%t\n", strings.Contains(a, "am")) //判断字符串a 中是否存在am
/*
true
true
true
*/
}
索引
strings.IndexRune(s,str string) int 用于Ascii编码
strings.LastIndex(s,str string) int 用于非Ascii编码
替换
一共有4个参数,其中第一个为原字符串,第二个表示需要被替换的子字符串,第三个表示替换内容,第四个则表示匹配到第几个,如果把上面的n改为数字-1,则表示匹配所有。
package main
import (
"fmt"
"strings"
)
//字符串替换
func main() {
str := "你好世界,这个世界真好!"
fmt.Println(strings.Replace(str, "世界", "地球", 1))
//你好地球,这个世界真好!
}
出现频率
strings.Count()
package main
import (
"fmt"
"strings"
)
//统计字符串中字符出现的频率
func main() {
a := "I am Le1aaaaa"
fmt.Println("a出现了: " + fmt.Sprint(strings.Count(a, "a")) + "次!")
}
字符串总数
package main
import (
"fmt"
"unicode/utf8"
)
//统计字符串数量
func main() {
s := "我爱中国"
fmt.Printf("%d\n", len([]rune(s)))//4
fmt.Println(utf8.RuneCountInString(s))//4
}
大小写转换
strings.ToLower(s)
strings.ToUpper(s)
package main
import (
"fmt"
"strings"
)
//大小写转换
func main() {
s := "I am Le1aaaaa,and I am 21"
fmt.Println(strings.ToLower(s)) //转化为小写
fmt.Println(strings.ToUpper(s)) //转化为大写
/*
i am le1aaaaa,and i am 21
I AM LE1AAAAA,AND I AM 21
*/
}
修剪
strings.Trim("今天天气真好","今天")//天气真好
分割
strings.Split("a,b,c",",")//以逗号,
来分割,得到["a","b","c"]
布尔型
布尔类型的表示
v:=true
直接表示 或者 v:=(1==2)
自动推导。go语言只有true和false,不能用0 1表示。