这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记
第一个当然是 hello,world啦
package main
import "fmt"
func main(){
fmt.Println("hello,world")
}
- Go语言类c++风格
- 每个Go程序必须包含一个main包以及一个main()函数。main()作为整个程序的入口,在程序执行时最先被执行。
- fmt包提供格式化文本和读入格式文本的函数,提供不同打印函数变体。fmt.Println()会整洁的打印输入的内容,fmt.Printf()使用占位符来提供良好的格式化输出控制能力。
- 程序没有分号,import语句也不用逗号分割,代码缩进仅仅为了提高代码可读性。从技术层面讲,Go的语句是以分号分隔,但这些是编译器自动添加,不需手动输入
- Go语言的函数和方法以关键字func定义,但main包里的main函数比较特别,既没有参数也没有返回值,当main.main()运行完毕,程序会自动终止并向操作系统返回0.
基础语法
-
使用 ":=" 进行声明变量并赋值操作,不需要 var 关键字;
使用 "=" 进行赋值操作,需要先 var 声明
定义常量则是将 var 改成 constvar a = 10 var b b = 10 d := 100 const s string = "constant" cosnt h = 5e10 -
循环结构之后for循环
if 之后没有括号,但必须接上大括号;import "fmt" if 7%2 == 0 { fmt.Println("7 is even") } -
另外还有一个改版,先执行 statement, 然后再判断 condition
if statement; condition { } if num := 9; num < 0 { fmt.Println(num, "is negative") } else if num < 10 { fmt.Println(num, "has 1 digit") } -
switch 语句,不同于 C & C++, 会case一旦对上,会自动break
a := 2
switch a {
case 1:
fmt.Println
}
- 使用切片,作为可变长度的数组
s := make([]string, 3)
- 变量类型后置
var s string
基本类型语法
package main
import (
"fmt"
"math"
)
func main(){
var a = "initial"
var b , c int = 1,2
var d=true
var e float64
f := float32(e)
g := a+"foo"
fmt.Println(a,b,c,d,e,f)
//initial 1 2 true 0 0
fmt.Println(g)
//initialfoo
const s string ="constant"
const h = 500000000
const i = 3e20/h
fmt.Println(s,h,i,math.Sin(h),math.Sin(i))
//constant 500000000 6e+11 -0.28470407323754404 0.7591864109375384
}
复制代码
- 操作符 := 快速变量声明。可以同时声明并初始化一个变量,不必声明一个具体类型的变量,Go语言可以从其初始化值推导其类型。go是强类型语言。
- 常量使用const声明,变量使用var声明,也可以快捷变量声明。
- var/const a int/float=
- 变量e没有显示初始化,会赋零值,字符串会默认为空。
- Go语言提供了大量内置的数值类型。不能在不同的类型之间进行二进制数值运算或比较操作。无类型的数值常量可以兼容表达式中任何类型的数值。将类型转换成最大的类型防止精度丢失以进行运算。type(value)
- 3e20是科学计数法 3*10^20
- Math.Sin(x) 以弧度为单位的x的正弦值
if语句
package main
import "fmt"
func main(){
if 7%2==0 {
fmt.Println("7 is even")
}else {
fmt.Println("7 is odd")
}
//if optionalStatement1;booleanExpression1 {}
if num:=8;num<0 {
fmt.Println(num,"is negetive")
}else if num<10{
fmt.Println(num,"has 1 digit")
}
}
复制代码
- if语句的大括号是强制性的,条件判断中的分号只有在可选语句optionalStatement出现的情况下需要。可选语句只能是表达式、发送到通道(使用<-操作符)、增减值语句、赋值语句或短变量声明语句。如果变量是在一个可选的声明语句中创建的(使用:=操作符创建),他们的作用于会从声明处扩展到if语句的完成处,他们在声明他们的if或elseif语句以及相应分支中一直存在,直到if语句的末尾。
- 第一个if语句的num变量扩展到了if...elseif...语句中,因此他们在每一个分支中都是可见的。
for循环
package main
import "fmt"
func main(){
i:=1
//for booleanExpression{block}
for{
fmt.Println("loop")
break
}
// for optionalPreStatement;booleanExpress;optionalPostStatement
for j:=7;j<9;j++{
fmt.Println(j)
}
for n:=9;n<5;n++ {
if n%2==0 {
continue
}
fmt.Println(n)
}
for i<=3 {
fmt.Println(i)
i=i+1
}
}
复制代码
switch循环
package main
import (
"fmt"
"time"
)
func main(){
a := 2
//switch optionalStatement{
switch a {
//case expressionList1:
//block
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
//default:bloakD
default:
fmt.Println("other")
}
t:=time.Now()
switch {
case t.Hour()<12:
fmt.Println("1")
default:
fmt.Println("2")
}
}
复制代码
- 不同于c和java,go的switch语句不会自动向下贯穿,因此不必在每个case字句末尾添加break语句,需要case
语句向下贯穿时可以显式调用fallthrough
- 没有可选的表达式语句,编译器会把表达式语句设为true。意味着case语句的每一个表达式都必须计算为布尔类型。
字符串切片
package main
import "fmt"
func main(){
s:=make([]string,3)
s[0]="a"
s[1]="b"
s[2]="c"
fmt.Println("get:",s[2])
fmt.Println("len:",len(s))
s=append(s,"d")
s=append(s,"e","f")
//[a b c d e f]
fmt.Println(s)
c:=make([]string,len(s))
copy(c,s)
//[a b c d e f]
fmt.Println(c)
//[c d e]
fmt.Println(s[2:5])
// [a b c d e]
fmt.Println(s[:5])
//[c d e f]
fmt.Println(s[2:])
good := []string{"g","o","o","d"}
fmt.Println(good)
}
复制代码
- [2:5] 从2-4
- [:5] 从0-4
- [2:] 从2到结尾 len(s)-1
- 切片 从开始到结束为止 不包含结束位置
make([]T,len)//长度为切片长度
make([]T,len,cap)//same as make([]T,cap)[:len] 长度为切片容量
复制代码
-
内置函数make创建指定元素类型、长度和容量的slice
- 创建一个隐藏的初始化为零值的数组,然后返回一个引用该隐藏数组的切片。
- 在底层,make创建了一个匿名的数组变量,返回一个slice。只有通过返回的slice才能引用底层匿名的数组遍历。
- 一个切片是一个隐藏数组的引用
-
对于append函数,每次调用会检测slice底层数组是否有足够容量来保存新添加的元素。如果空间足够,直接扩展slice(在原有的底层数组上),将新添加的元素复制到新扩展的空间,并返回slice。输入和输出共享相同的底层数组。
- 如果没有足够的增长空间,会先分配一个足够大的slice用于保存新的结果,将输入复制到新的空间,然后添加一个新元素。输入和输出引用的是不同的底层数组。
- 内置的append函数可能使用比appendInt更复杂的内存扩展策略。因此通常不知道append是否导致了内存的重新分配,也不能确定原始slice和新的slice引用的是否是相同的底层数组空间。通常是将append返回的结果直接赋值给输入的slice变量。
-
内置的copy元素可以方便的将一个slice复制到另一个相同类型的slice。copy的第一个参数是要复制的目前slice,第二个参数是源slice。两个slice可以共享一个底层数组,有重叠也没问题。copy函数将返回成功赋值的元素的个数(这里没有用到),等于两个slice中较小的长度,所以无须担心复制会超出目标slice的范围。
map
package main
import "fmt"
func main(){
m:=make(map[string]int)
m["one"]=1
m["two"]=2
//map[one:1 two:2]
fmt.Println(m)
//2
fmt.Println(len(m))
//1
fmt.Println(m["one"])
//0
fmt.Println(m["unknow"])
r,ok := m["unknow"]
//0 false
fmt.Println(r,ok)
delete(m,"one")
m2:=map[string]int{"one":1,"two":2}
var m3 = map[string]int{"one":1,"two":2}
fmt.Println(m2,m3)
}
复制代码
-
map保存键值对的无序结合。键唯一
-
m[k]=v 用键k来将值v赋值给映射m。如果映射m中的k已存在,将之前的值丢弃。
-
v,found := m[k] 从映射m中取得键相对应的值并将其赋值给v,并将found的值赋值为true。如果k在映射中不存在,则将映射类型为0值赋值给v,并将found的值赋值为false。
-
delete(m,k) 将键k及相关的值从映射m中删除,如果k不存在则安全地不执行任何操作
-
v:=m[k] 从映射m中取得键k相对应的值并将其赋值给v。如果k在映射中不存在,将映射类型的0值赋值给v。类似于Java的getOrDefault(k,0)
-
len(m) 返回映射m中项("键/值"对)的数目
-
map[KeyType]ValueType{key1:value1,key2:value2...}
-
用make()创建的映射得到的是空的映射,指定容量就会预先申请到足够的内存,随着加入的项越来越多映射会自动扩容。
- make(map[KeyType]ValueType)
函数
- golang中变量后置
package mai
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
// 创建一个新的结构体
fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})
// 也可以使用 key => value 格式
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})
// 忽略的字段为 0 或 空
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})
}
输出结果为:
{Go 语言 www.runoob.com Go 语言教程 6495407}
{Go 语言 www.runoob.com Go 语言教程 6495407}
{Go 语言 www.runoob.com 0}