基本语法
变量
-
可以手动确定类型,也可自动识别
var i = 1 int j = 1或者通过利用冒号语法
f := float32(0) -
不可变常量,没有类型,自动转化
const s string = "constant"
分支
if 语句
相对于 c 语法,if 后面没有括号,但必须跟上分号
Switch 语句
不需要在每个case 后面跟上break;可以在 switch 后面不加任何的变量,然后在 case 里面写条件分支。这样代码相比用多个 if else 代码逻辑会更为清晰
switch {
case t.Hour() < 12 :
fmt.Println("It's before noon.")
default:
fmt.Println("It's afternoon.")
}
循环
只能使用for循环,也没有分号;可以配合 range 使用
基本元素集合
数组
声明数组
a := [5]int{1,2,3,4,5}
数组的访问就是经典方式
slice
通过 make数组获得,通过第二个参数指定长度
s := make([]string, 3)
可以使用append方法追加元素,需要重新赋值
s = append(s, "d")
使用copy方法拷贝
Map
声明时指定两种类型,中括号内为key,外面为value
m := make(map[string]int)
访问 Map 元素时,若key对应的值不存在,则会返回 0 和 false (两个值)
删除元素通过delete方法,删除 key 对应的键值对元素,此处删除的是名为m["one"]
delete(m, "one")
range
可以用来快速遍历数组,slice,map等
for 循环中使用时,返回两个值,第一个值为index,第二个值为value;对于map,第一个为key
nums := []int{1,2,3}
for i, num := range nums {
fmt.Pringln(i, num)
}
函数
通过 func关键字指出;参数类型后置;返回类型在最后
func add(a int, b int) int {
return a + b
}
并且可以返回多个值(一般为两个),常常使用第二个参数表示是否错误
指针
一般在函数中使用,用于传递参数;在函数内部直接修改原对象的值(不是拷贝值);
func add2ptr(n *int, a int) {
*n += a
}
n := 2
add2ptr(&n, 1)
结构体
type user struct {
name string
password string
}
结构体赋值:
a := user{name: "wang", password: "1024"}
b := user{"wang", "1024"}
结构体方法
可以使用指针,修改结构体内的值
func (u user) checkPassword(password string) bool {
return u.password == password
}
func (u *user) resetPassword(password string) {
u.password = password
}
错误处理
在函数中使用单独的error返回值表示,然后通过简单的if-else语句处理
if err != nil{
fmt.Pringln(err)
return
}
常用方法
JSON 处理
对于一个已有的结构体,保证其字段的首字母为大写,只需使用JSON.marshaler 去序列化,就能变成一个JSON字符串;可以在结构体字段的后面使用JSON tag ,修改JSON字符串的字段名
type userInfo struct {
Name string
Age int `json:"age"
Hobby []string
}
//...
a := userInfo{Name: "wang", Age: 18, Hobby: []string{"golang", "TypeScript"}}
buf, err := json.Marshall(a)
if err != nil{
panic(err)
}
fmt.Println(buf)
数字解析
字符串转换成整型或浮点型数字,使用strconv包
f, _ := strconv.ParseFloat("1.234", 64)
n, _ := strconv.ParseInt("111", 10, 64)//十进制,精度为64
或者使用自动转化strconv.Atoi()
实战
猜谜游戏
-
生成随机数
randmax := 100 rand.Seed(time.Now().UnixNano()) secretNumber := rand.Intn(maxNum)利用系统时间作为种子
-
获取用户输入
os.Stdin通过bufio或者fmt.scanf获取reader := bufio.NewReader(os.Stdin) input, err := reader.ReadString('\n') input = strings.TrimSuffix(input, "\n") // 去除字符串后缀 guess, err := strconv.Atoi(input) // 字符串转换 -
然后实现判断逻辑和循环即可
在线词典
要点:发送http请求,解析JSON数据
发送http请求
生成请求可以通过Convert curl commands to code
-
创建客户端
client := &http.Client -
创建流数据
data := string.NewReader("") -
创建请求,设置请求头
req, err := http.NewRequest("POST", {url}, data) req.Header.Set()// 通过工具生成 -
发送请求
resp, err := client.Do(req) -
关闭请求体
defer resq.Body.Close() -
读取返回结果,利用
ioutil.ReadAllbodyText, err := ioutil.ReadALL(resp.Body)使用
ioutil.ReadAll可以快速将数据从io.reader读取出来。但是当遇到大文件时,这个函数就会暴露出两个明显的缺点:- 性能问题,文件越大,性能越差。
- 文件过大的话,可能直接撑爆内存,导致程序崩溃。
解析 JSON
-
创建对应的结构体, 使用JSON转Golang Struct - 在线工具 - OKTools
-
将返回结果去序列化
var dicResponse DictResponse // DictResponse为创建的结构体 err = json.Unmarshal(bodyText, &dictResponse) -
然后可以通过
dictResponse.字段的方式获取对应字段数据
SOCKS5代理
提供一个代理服务, 先与源主机建立连接, 然后与目标主机建立连接, 此后作为中介在两者间传递信息, 实现协议内容关键在于对报文的处理
-
开启监听端口, 并获取请求信息
server, err := net.Listen("tcp", "127.0.0.1:1080") for { client, err := server.Accept() }