这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
Go笔记
Day_01基础语法
helloWorld
package main
import("fmt")//格式化字符串
func main(){
fmt.Println("hello world")
}
一、变量类型:
| 类型 | 描述 |
|---|---|
| 布尔型 | 布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。 |
| 数字类型 | 整型 int 和浮点型 float32、float64,Go 语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。 |
| 字符串类型 | 字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。 |
| 派生类型 | 指针类型(Pointer)、数组类型 、结构化类型(struct) 、 Channel 类型、 函数类型、 切片类型 、接口类型(interface) 、Map 类型 |
二、变量声明:
指定变量类型,如果没有初始化,则变量默认为零值。
根据值自行判定变量类型。
如果变量已经使用 var 声明过了,再使用 := 声明变量,就产生编译错误,
:= 相当于是一个声明语句
var name = value
var name,name type = value,value
name := value
//类型相同多个变量, 非全局变量
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3
var vname1, vname2, vname3 = v1, v2, v3 // 和 python 很像,不需要显示声明类型,自动推断
vname1, vname2, vname3 := v1, v2, v3 // 出现在 := 左侧的变量不应该是已经被声明过的,否则会导致编译错误
// 这种因式分解关键字的写法一般用于声明全局变量
var (
vname1 v_type1
vname2 v_type2
)
值类型和引用类型
所有像 int、float、bool 和 string 这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值:
当使用等号 = 将一个变量的值赋值给另一个变量时,如:j = i,实际上是在内存中将 i 的值进行了拷贝:
这里可以使用指针进行解释。
三、常量:
将var改成const
const name type = value
//多个常量赋值
const c_name1, c_name2 = value1, value2
你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型。
- 显式类型定义:
const b string = "abc" - 隐式类型定义:
const b = "abc"
常量还可以使用枚举的方式来定义
const{
Unknown = 0
Female = 1
Male = 2
}
iota特殊常量
使用时,从0开始,然后每使用一次就+1,这个常量可以用来被编译器修改的常量值
iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。
cosnt{
a = iota//0
b = iota//1
c = iota//2
}
四:条件if else:
if 7%2 == 0{
fmt.println("7 is even")
} else{
fmt.println("7 is odd")
}
if 8%4 == 0{
fmt.println("8 is divisible by 4")
}
if num := 9;num < 0{
fmt.println(num,"is negative")
} else if num < 10{
fmt.println(num,"has 1 digit")
} else{
fmt.println(num,"has multiple digits")
}
if后面没有括号,写了括号的话,编辑器会自动去除括号,不能将if里面的语句和判断条件写在同一行,if后面必须加{}
五:循环
//死循环
for{}
//遍历0到4
for num := 0; num < 5; num++ {
fmt.println(num)
}
for number := 0; number < 5; number++{
if num % 2 == 0{
fmt.println(number)
}
}
i := 0
for i <= 3{
fmt.println(i)
i = i + 1
}
只有for循环,没有其他循环,和if语法类似,不需要小括号,必for后面须加{},可以使用continue继续,break跳出
六:分支switch
a := 2
switch a{
case 1:
fmt.println("one")
case 2:
fmt.println("two")
case 3:
fmt.println("three")
case 4,5:
fmt.println("four or five")
default:
fmt.println("other")
}
t := time.Now()//获取当前时间
switch {
case t.Hour() < 12:
fmt.println("morning")
default:
fmt.println("afternoon")
}
switch里面的case语句不需要每一行都写break,go语言会自动判定,可以任意变量类型,可以替代if else
七:数组array
//定义数组
var a [5]int//长度为5的一个整型数组
八:切片
不同于数组,是一个可变长度的数组,可以随时变更长度
Go 语言切片是对数组的抽象。
Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。
//定义切片
s := make([]string,3)//初始长度为3的一个字符串切片
//给切片赋值,和数组差不多
s[0] = "a"
s[1] = "b"
s[2] = "c"
//遍历切片的值
for i := 0;i < len(s);i++{
fmt.println(s[i])
}
//追加切片并赋值
s = append(s,"d")
s = append(s,"e","f")
fmt.println(s)//[a,b,c,d,e,f]
//切片间的赋值
c := make([]string,len[s])
copy(c,s)
fmt.println(c)//[a,b,c,d,e,f]
fmt.println(s[2:5])//[c,d,e],从第2个元素开始(不包括第二个)到第5个结束(包括第5个)
fmt.println(s[:5])//[a,b,c,d,e]
fmt.println(s[2:])//[c,d,e,f]
如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。
可以通过设置下限及上限来设置截取切片 [lower-bound:upper-bound] 。
切片是可索引的,并且可以由 len() 方法获取长度。
切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。
九:字典(哈希)map
Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
//定义一个map
m := make(map[string]int)//定义一个字符串字典来存放int类型的值
m["one"] = 1
m["two"] = 2
fmt.println(m)
fmt.println(m["one"])
fmt.println(m["unkonwn"])//0
r,ok := m["unknown"]//(等于号有判断的作用)判断m中是否含有这个键
fmt.println(r,ok)//0 false
delete(m,"one")//删除字典m中的键为one的键和值
//创建map并赋值
m2 := map[string]int{"one" : 1,"two" : 2}
var m3 = map[string]int{"one" : 1,"two" : 2}
fmt.println(m2,m3)
遍历时完全无序,随机顺序
十:range(排列)
Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。
array、slice和map可以采用range去遍历
nums := []int{1,2,3,4,5}
sum := 0
//遍历数组
for i,num := range nums{
sum += num
if num == 2{
fmt.println("index:",i,"num:",num)//index1 num:2
}
}
//遍历map
m := map[int]string{1:"A",2:"B",3:"C"}
for i,mValue := range m{
fmt.println(mValue)
}
for k := range m{
fmt.println("key",k)
}//当只有一个参数时,默认为key
range需要两个参数,第一个是获取的索引,第二个是获取的值
十一:函数
至少有一个main函数,主函数
//定义一个函数
func name([parameter list]) [return_types]{
函数体
}
//name为函数名,
//parameter list参数列表
//return_types返回类型
go语言函数可以返回多个值
func swap(x,y)(string,string){
return x,y
}
func main(){
a,b := swap("go","od")
fmt.println(a,b)
}
函数如果使用参数,该变量可称为函数的形参。
形参就像定义在函数体内的局部变量。
十二:指针
指针使用流程:
- 定义指针变量。
- 为指针变量赋值。
- 访问指针变量中指向地址的值。
&取地址符
*取内容符
//定义一个指针变量
ptr *int
func add(n int){
n += 2
}
func addPtr(n *int){
*n += 2
}
func main() {
n := 5
add(n)
fmt.println(n)//5
addPtr(&n)//&取地址符
fmt.println(n)//7
}
十三:结构体
//定义一个结构体
type user struct{
name string
address string
}
个人理解相当于Java中的实体类,可以结合Java的实体类来学习
结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,结构体中有一个或多个成员。
十四:error(错误处理)
Go 语言通过内置的错误接口提供了非常简单的错误处理机制。
error类型是一个接口类型,这是它的定义:
type error interface {
Error() string
}
我们可以在编码中通过实现 error 接口类型来生成错误信息。
函数通常在最后的返回值中返回错误信息。使用errors.New 可返回一个错误信息:
func Sqrt(f float64) (float64, error) {
if f < 0 {
return 0, errors.New("math: square root of negative number")
}
// 实现
}
十五:Strings
结合Java的string类来学习。
十六:fmt(格式化)
结合Java中的system.out来学习,大同小异
十七:JSON
对字符串进行序列化
十八:时间处理(time)
进行时间格式化格式不能使用其他语言格式(yyyy-MM-dd hh:mm:ss)而是使用的特定的一个时间(2006-01-02 15:04:05)
now.Unix()获取时间戳的方法
十九:数字解析
使用strconv库,里面的方法可以对数字进行处理
二十:进程信息
使用os库