这是我参与「第五届青训营 」伴学笔记创作活动的第 1天
1.1 go语言安装
在Downloads - The Go Programming Language 网址下载go的安装包
无脑安装
1.2 ide goland 安装
在goland官网找到2021.3.4版本的开发环境,下载并安装
安装好之后 可以在链接GoLand 激活方法 2022版 最新简易教程 (52shizhan.cn)中获取激活码,然后使用插件进行激活,最后我的ide的激活日期如下图所示:
已经激活到5000年
1.3 环境配置
在goland文件夹中新建goworkStation文件夹,并在此文件夹下新建如下文件夹,
其中bin中存放编译安装程序目录,pkg中存放依赖,src中为项目源码
在系统环境变量中,添加goroot、gopath目录,并将其添加至path目录中,如下图所示
在命令行窗口查看安装的go版本
此时环境配置成功
2 简介
Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。
Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 ,Go语言是一个非常现代化的语言,精小但非常强大。
Go 语言最主要的特性:
- **自动垃圾回收
- **更丰富的内置类型
- **函数多返回值
- **错误处理
- **匿名函数和闭包
- **类型和接口
- **并发编程
- **反射
- **语言交互性
2.1 第一个demo
在goland中新建go文件,然后将以下代码输入编译、运行
package main
import "fmt"
func main() {//左大括号必须和函数名同一行,否则报错
fmt.Println("hello,world")//分号可加可不加
}
结果
2.2 变量和常量(iota)
package main
import (
"fmt"
"math"
)
func main() {
//局部声明变量方式1
var a int
fmt.Println("a=", a)
//声明变量方式2
var b int = 100
fmt.Println("b=", b)
//声明变量方式3
var c = 200
fmt.Println("c=", c)
fmt.Printf("c=%v,type of c=%T\n", c, c)
//声明变量方式4(常用)
e := 300
fmt.Printf("e=%v,type of e=%T\n", e, e)
f := float64(e)
fmt.Printf("f=%f,type of f=%T\n", f, f)
//常量
const eh = 2000
const i = eh / 4
fmt.Println(eh, math.Sin(i))
//多个变量
var ll, yy = 123, "sad"
fmt.Println(ll, yy)
}
全局变量没有第四种方式
iota:自增,仅可以在const中使用,默认值为0
const (
u1 = iota * 10 //iota=0
u2 //iota=1,u2=10
u3 //iota=2,u3=20
)
fmt.Println(u1, u2, u3)
2.3 流程控制语句
go语言中的if else和C+类似。不同点是条件没有(),如是写的话,那么在保存的候编译器会合自动去掉。第二个不同点是后面必须跟大活号
if num := 9; num < 0 {
fmt.Println("是负数")
} else {
fmt.Println("不是负数哦")
}
switch语句 1、go中的switch语句和C++比较类似,区别是switch后面的那个变量名不加括号 2、除此之外,在执行一个case之后,在C++中如果不加break语句,则程序会一直执行结束,直到遇到break为止,但在go中是不需要加break的 3、go中的switch语句可以使用任意的变量类型,甚至可以取代if else语句,例如可以在switch语句中不加变量然后在case中写逻辑,可以使代码更清晰
//switch
grade := "A"
switch {
case grade == "A":
fmt.Printf("优秀!\n")
case grade == "B", grade == "C":
fmt.Printf("良好\n")
case grade == "D":
fmt.Printf("及格\n")
case grade == "F":
fmt.Printf("不及格\n")
default:
fmt.Printf("差\n")
}
2.4 循环
在go中只有一种循环,即for循环,最简单的循环就是一个for+{} 代表死循环,可以使用continue和break来跳出或者继续
qq := -5
for qq <= 0 {
fmt.Println(qq)
qq++
}
//for {
// time.Sleep(5 * time.Second)
//}
for i := 0; i < 5; i++ {
fmt.Println("我爱学go")
}
//结果
-5
-4
-3
-2
-1
0
我爱学go
我爱学go
我爱学go
我爱学go
我爱学go
2.5 数组
在真实的业务里面很少使用数组,通常使用切片 数组的语法如下
//数组
//var variable_name [SIZE] variable_type
var balance [10]float32 //数组长度不确定可以使用[]
balance[0] = 1
//初始化数组
var balance1 = []float32{1000.0, 2.0, 3.4, 7.0, 50.0}
//或者
balance2 := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
fmt.Println(len(balance1))
//可以指定具体位置的元素
balance3 := [5]float32{1: 2.0, 3: 7.0}
balance1[0] = 4
balance2[0] = 4
balance3[0] = 4
var twoD [2][3]int
twoD[0][0] = 1
2.6 切片
Go 语言切片是对数组的抽象。
Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。 slice的初始化
//定义方式1
var identifier []type
//定义方式2
slice1 := make([]type, len)
//slice
slice1 := make([]int, 3)
slice1[0] = 0
slice1[1] = 1
fmt.Println(len(slice1))
slice1 = append(slice1, 12)
fmt.Println(slice1)
qw := make([]int, 3)
copy(qw, slice1[:3]) //此处不包括3位置的元素
fmt.Println(qw)
2.7 map
map是实际过程中使用最多的数据结构,golang中的map是无序的,遍历的时候也不会按照顺序,他的顺序是随机的。
//map
var map1 = make(map[string]int)
map1["one"] = 1
map1["two"] = 2
fmt.Println(map1)
fmt.Println(len(map1))
r, ok := map1["three"]
fmt.Println(r, ok)
delete(map1, "one")
fmt.Println(map1)
2.8 range
我们可以使用range来快速遍历map和slice,在遍历的时候回返回两个值,第一个是索引,第二个是对应的值,如果不需要用索引的话,可以使用下划线忽略
//range
nums := []int{1, 2}
sum := 0
for i, num := range nums {
sum += num
fmt.Printf("sum is %d,index is %d", sum, i)
}
map2 := make(map[string]int)
map2["ss"] = 8
for k, v := range map2 {
fmt.Println(k, v)
}
2.9 函数
go和其他的语言的不同之处在于,他的变量类型是后置的,并且可以返回多个值,在真实的业务中也是返回两个,第一个是真正的返回结果,第二个是错误信息
//函数
map3 := make(map[string]int)
map3["sa"] = 1
v, ok := exists(map3, "sa")
fmt.Println(v, ok)
}
func exists(m map[string]int, k string) (v int, ok bool) {
v, ok = m[k]
return v, ok
}
2.10 指针
go中的指针支持的操作有限,一个重要的用途是对于传入的参数进行修改,和C++中使用方法差不多 如下代码所示
n := 1
add1(&n)
fmt.Println(n)
}
func add(a int) {
a = a + 2
}
func add1(a *int) {
*a = *a + 2
}
2.11 结构体
//结构体
struct1 := user{"ccc", "1234"}
struct2 := user{}
struct2.name = "sdksd"
fmt.Println(struct1)
fmt.Println(checkPassword(struct1, "1234"))
}
type user struct {
name string
password string
}
func checkPassword(u user, password string) bool {
return u.password == password
}
func checkPassword1(u *user, password string) bool {
return u.password == password
}
类似于C中的结构体,不多赘述
2.11.1 结构体方法
//结构体方法
res := struct2.checkPassword("1234")
fmt.Println(res)
}
type user struct {
name string
password string
}
func (u user) checkPassword(password string) bool {
return u.password == password
}
可以为结构体定义方法,类似于其他语言中的类成员函数,只需要在函数头开头()放入结构体即可,如上图所示
2.12 错误处理
错误处理在go中的做法是使用单独的返回值来传递错误信息,go中没有异常,在函数实现的时候,return需要返回两个值,如果出现错误的话,可以返回nil和error,如果正确的话则返回原本的结果和nil
//错误处理
user1 := []user{{"cc", "123"}}
u, err := findUser(user1, "cc")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name)
}
func findUser(users []user, name string) (v *user, err error) {
for _, u := range users {
if u.name == name {
return &u, nil
}
}
return nil, errors.New("not found")
}
2.13 字符串操作
//字符串处理
str := "hello1"
str1 := "hello2"
strr := []string{str, str1}
fmt.Println(strings.Contains(str, "ll"))
fmt.Println(strings.Count(str1, "l"))
fmt.Println(strings.Index(str, "l"))
fmt.Println(strings.Join(strr, "-"))
fmt.Println(strings.Replace(str, "he", "hh", -1))
fmt.Println(strings.ToUpper(str))
格式化输出 常用的两种 println和printf 前者类似于java中的标准输出 后者类似于c语言中的输出
//格式化输出
n1 := 123
p := point{1, 2}
fmt.Println(n1, p)
fmt.Printf("s=%v\n", str)
fmt.Printf("s=%v\n", p)
2.14 json操作
一个现有的结构体需要转化为json时,只需要将结构体的每一个成员首字母大写(即让其变为公开字段)即可使用 json.Marshal 方法对其进行序列化。同时我们也可以对一个序列化后的字符串使用 json.Unmarshal 进行反序列化。在输出时要使用 string 类型转换,否则将输出为十六进制数字。如果不想要输出的字段名为大写,可以给字段后加加一个 tag 或者说是别名。
//json
aa := userInfo{"wang", 23, []string{"love", "ll"}}
buf, err := json.Marshal(aa)
if err != nil {
panic(err)
}
fmt.Println(buf)
fmt.Println(string(buf))
//buf, err = json.MarshalIndent(aa, "", "\t")
var bb userInfo
err = json.Unmarshal(buf, &bb)
if err != nil {
panic(err)
}
fmt.Printf("序列化结果%v", bb)
}
2.15 时间处理
//时间处理
now := time.Now()
fmt.Println(now) //2023-01-16 20:02:02.7679312 +0800 CST m=+0.00582790
//使用time.date构造时间
t := time.Date(2023, 1, 16, 1, 25, 60, 0, time.UTC)
t1 := time.Date(2024, 1, 16, 1, 25, 60, 0, time.UTC)
fmt.Println(t)
diff := t1.Sub(t)
fmt.Println(diff)
fmt.Println(now.Format("2006-01-02 15:04:05"))
//获取时间戳
fmt.Println(now.Unix())
2.16 数字解析
//数字解析
f, _ = strconv.ParseFloat("1.23456", 64)
fmt.Println(f)
n12, _ := strconv.ParseInt("11", 10, 64)
fmt.Println(n12)
nn, _ := strconv.Atoi("123456")
fmt.Println(nn)
可以用strconv包下的函数进行转换,是string convert的缩写 可以用parseInt或者parseFloat 解析字符串,也可以用Atoi把字符串转化为数字,或者itoA把数字转化为字符串
3 案例
猜数字
package main
import (
"fmt"
"math/rand"
"strconv"
"time"
)
func main() {
maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)
fmt.Println("请输入你的数字:")
var input string
//reader := bufio.NewReader(os.Stdin)
for {
//input, err := reader.ReadString('\n')
//if err != nil {
// fmt.Println("输入发生错误", err)
// return
//}
//input = strings.TrimSuffix(input, "\r\n")
//fmt.Printf("%#v", input)
//fmt.Scanf("%s", &input)
fmt.Scanf("%s\n", &input)
fmt.Printf("%#v", input)
guess, err := strconv.Atoi(input)
if err != nil {
fmt.Println("转换出错")
}
fmt.Println("your guess: ", guess)
if guess > secretNumber {
fmt.Println("大了")
} else if guess < secretNumber {
fmt.Println("小了")
} else {
fmt.Println("对了")
break
}
}
}
遇到几个问题 使用scanf在输入时,循环会执行两次,查阅资料后发现是因为输入的换行符也会被处理,因此需要在%s加\n,可以使用scan或者scanln更方便 可以看这个博客 blog.51cto.com/u_14454410/…
在线词典
在火狐浏览器请求,可以看到参数和响应
然后使用curl工具将其转化为go的格式
链接如下
Convert curl to Go (curlconverter.com)
将json转化为结构体 在线工具 - OKTools
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
UserID string `json:"user_id"`
}
func query(word string) {
client := &http.Client{}
request := DictRequest{TransType: "en2zh", Source: word}
buf, err := json.Marshal(request)
data := bytes.NewReader(buf)
//将字符串转化为流
//var data = strings.NewReader(`{"trans_type":"en2zh","source":word}`)
//创建请求
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
if err != nil {
log.Fatal(err)
}
//添加请求头
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0")
req.Header.Set("Accept", "application/json, text/plain, */*")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2")
// req.Header.Set("Accept-Encoding", "gzip, deflate, br")
req.Header.Set("Content-Type", "application/json;charset=utf-8")
req.Header.Set("X-Authorization", "token:qgemv4jr1y38jyq6vhvi")
req.Header.Set("app-name", "xy")
req.Header.Set("version", "1.8.0")
req.Header.Set("os-type", "web")
req.Header.Set("Origin", "https://fanyi.caiyunapp.com")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Referer", "https://fanyi.caiyunapp.com/")
req.Header.Set("Sec-Fetch-Dest", "empty")
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "cross-site")
req.Header.Set("TE", "trailers")
//发起请求
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
//body是流,避免资源泄漏,defer会在函数执行完之后去执行
defer resp.Body.Close()
bodyText, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
//fmt.Printf("%s\n", bodyText)
var bodyResp AutoGenerated
err = json.Unmarshal(bodyText, &bodyResp)
if err != nil {
log.Fatal(err)
}
fmt.Println(bodyResp.Dictionary.Explanations)
}
type AutoGenerated struct {
Rc int `json:"rc"`
Wiki struct {
KnownInLaguages int `json:"known_in_laguages"`
Description struct {
Source string `json:"source"`
Target interface{} `json:"target"`
} `json:"description"`
ID string `json:"id"`
Item struct {
Source string `json:"source"`
Target string `json:"target"`
} `json:"item"`
ImageURL string `json:"image_url"`
IsSubject string `json:"is_subject"`
Sitelink string `json:"sitelink"`
} `json:"wiki"`
Dictionary struct {
Prons struct {
EnUs string `json:"en-us"`
En string `json:"en"`
} `json:"prons"`
Explanations []string `json:"explanations"`
Synonym []string `json:"synonym"`
Antonym []string `json:"antonym"`
WqxExample [][]string `json:"wqx_example"`
Entry string `json:"entry"`
Type string `json:"type"`
Related []interface{} `json:"related"`
Source string `json:"source"`
} `json:"dictionary"`
}
func main() {
var word string
count, err := fmt.Scanln(&word)
if err != nil {
fmt.Println(err, count)
}
query(word)
}