这是我参与「第五届青训营 」伴学笔记创作活动的第1天
前言
本人小白,专科软件技术大二,欢迎大家欢迎大家批评与指正
Go语言的基本介绍
Go语言是一门:静态强类型、编译并发型语言,也是区块链最主流的编程语言。
公式:Go = C+Python{拥有静态运行速度,动态快速开发}
1. 基本功能介绍
- (1)Go语言从C语言中继承了很多理念,包括表达式语法、控制结构、基础数据类型、调用参数传值、指针等等,也保留了和C语言一样的编译执行方式及弱化的指针
- (2) 引入包的概念,用于组织程序结构,Go语言的一个文件都要归属于一个包,而不能单独存在。
- (3) 垃圾回收机制。内存自动回收,不需要开发人员管理,防止造成内存泄露
- (4) 天然并发性能。从语言层面支持并发,实现简单
- (5) 吸收了管道通信机制。形成Go语言特有的管道channel。通过管道channel可以实现不同的goroute之间的相互通信
- (6) 函数可以返回多个值
- (7) 新的创新比如切片(slice)、延时执行defer等
2.吉祥物:【金花鼠】
Go语言的快速入门&课程代码剖析
1、变量&introduce
Go语言主要有四种类型的声明语句:var、const、type和func,分别对应变量、常量、类型和函数实体对象的声明。
变量的两种声明方式
一般类型:“var 变量名字 类型 = 表达式”//自己定义变量类型
简短变量声明:“名字 := 表达式”//自动推导类型
不给变量赋值时,接口或引用类型(包括slice、指针、map、chan和函数)变量对应的零值是nil
简短变量声明被广泛用于大部分的局部变量的声明和初始化。var形式的声明语句往往是用于需要显式指定变量类型的地方,或者因为变量稍后会被重新赋值而初始值无关紧要的地方。
1.1变量&Code
`/* 变量 */
var a = "Hiro"
var b, c int = 1, 2
var d = true
var e float64
f := float32(e) // 创建变量并赋值
g := a + "llj"
fmt.Println(a, b, c, d, e, f, g)
/* 匿名变量 */
_, v, _ := getData()
fmt.Println("匿名变量", v)
/* 常量 */
const s string = "constant"
const h = 500000000
const i = 3e20 / h
ft.Println(s, h, i, math.Sin(h), math.Sin(i))`
未定义类型可自动识别,定义了数据类型未赋值编译不报错,编译器给定默认初始值
2、指针&introduce
2.1指针&Code
func add(n int) {
n += 2
}
func addPtr(n *int) {
*n += 2
}
func main() {
x := 5
add(x)
fmt.Println(x) //5
addPtr(&x)
fmt.Println(x) //7
}
两个函数一个接收的参数是基本类型,一个是指针类型,两个函数对变量n进行相同操作,但是输出的值却不同?
解释:因为形参(n int)接收的是x的地址值,x地址值里存放的是5,函数内n取到的是n存放的地址值的值”5“,*n += 2其实改变的是x地址存放的值,所以结果输出7
如图:
3、系列(range)
Go语言可以使用for range遍历数组、切片、字符串、map及通道(channel)
数组、切片、字符串返回索引和值。
map 返回键和值。
通道(channel)只返回通道内的值。
遍历数组、切片——获得索引和元素
3.1系列(range)&Code
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
sum += num
if num == 2 {
fmt.Println("index:", i, "num:", num)
}
}
fmt.Println(sum)//index: 0 num: 2
m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
fmt.Println(k, v)
}
for k := range m {
fmt.Println("key", k)
}
定义一个nums切片里面存了值"2,3,4";i为数组下标,num为数组下标对应的值,当num==2时输出index和num
map类型可以写为map[K]V,其中K和V分别对应key和value的数据类型”{}“输入的是键值对;两种遍历第一种显示key和value;第二种只输出value
4、数组&Slice
切片:
Golang中的切片,不是拷贝,而是定义了新的指针,指向了原来数组所在的内存空间所以,修改了切片数组的值,也就相应的修改了原数组的值了
- 切片并不存储任何数据,它只是描述了底层数组中的一段。
- 更改切片的元素会修改其底层数组中对应的元素。
- 与它共享底层数组的切片都会观测到这些修改。
4.1数组&Code
/* 数组声明 */
str := [4]string{
"aaa", "bbb", "ccc", "ddd",
}
fmt.Println(str)
/* 数组切片·[上界:下界) */
a := str[0:2]
b := str[1:3]
fmt.Println(a, b) //aaabbb bbbccc
b[0] = "XXX" //取某一片段没有分配地址空间
fmt.Println(a, b) //aaabbb XXXccc
fmt.Println(str) //不变还是 aaa XXX ccc ddd
/* make(数据类型,len,cap) 创建动态数组 */
num := make([]int, 5) //len(aq) = 5 指定长度
num[0] = 3
num[1] = 4
fmt.Println("len:", len(num))
num = append(num, 5, 6, 7)
fmt.Println(num, "len:", len(num))
fmt.Println(num[2:5])
fmt.Println(num[2:])
fmt.Println(num[:5])
good := []string{"g", "o", "o", "d"}
fmt.Println(good)
5、集合(Map)&Using
内置的make函数可以创建一个map:
ages := make(map[string]int)
也可以用map字面值的语法创建map,同时还可以指定一些最初的key/value:
ages := map[string]int{
"alice": 31,
"charlie": 34,
}
//相当于
ages := make(map[string]int)
ages["alice"] = 31
ages["charlie"] = 34
使用内置的delete函数可以删除元素:
delete(ages, "alice") // remove element ages["alice"]
如果元素类型是一个数字,你可能需要区分一个已经存在的0,和不存在而返回零值的0,可以像下面这样测试:
age, ok := ages["bob"]
if !ok { /* "bob" is not a key in this map; age == 0. */ }
5.1集合(Map)&Code
/* map */
m := make(map[string]int) //key:value
m["one"] = 1
m["two"] = 2
fmt.Println(m)//map[one:1 two:2]
fmt.Println(len(m))//2
fmt.Println(m["one"])//1
fmt.Println(m["unknow"])//0
//判断key是否存在
r, ok := m["unknow"]
fmt.Println(r, ok)//0 false
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[one:1 two:2] map[one:1 two:2]
- 使用内置的make函数创建一个map,对map指定两组key:value,打印输出键值对、长度、"one"和"unkonw"的值,"unkonw"不存在则返回0。
- 可以使用ok判断"unkonw"是否是存在,存在输出相应的值和true
- 删除m中"one"的值
- 使用map字面值的语法创建map
6、函数
//方法的定义:
func (recevier type) methodName (参数列表)(返回值列表){
方法体
return 返回值
}
//recevier type 结构体或自定义类型
6.1函数&Code
func main() {
fmt.Println(add(2, 3))
list := map[string]string{"a": "A", "b": "B"}
fmt.Println(exists(list, "a")) //判断key "a" 在map中是否存在
}
//计算两个数的和
func add(a, b int) int {
return a + b
}
//判断map中是否有指定的键值,有的话返回该键值判断为true(否者return 0,false)
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
7、语句
7.1语句&Code
package main
import (
"fmt"
"math"
"time"
)
func main() {
fmt.Println(pow(2, 2, 10)) //输出小于v的x^n
fmt.Println(cycleFor()) //for循环1-100的和
cycleSwitch() //switch比较目前时间
delay() //
fmt.Println(add(13, 14)) //13+14
a, b := swap("Hello", "World")
fmt.Println(a + b)
}
/* if语句 */
func pow(x, n, lim float64) int { //返回值类型
if v := math.Pow(x, n); v < lim {
return int(v) //强制类型转换int()
}
return int(lim)
}
/* 循环语句 */
func cycleFor() int {
sum := 1
for sum <= 100 {
sum += sum
}
return sum
}
/* switch语句 */
func cycleSwitch() {
t := time.Now() //显示目前的时间
fmt.Println(t)
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
}
/*
defer语句:
将函数推迟到外层函数返回之后执行(从下向上执行)
语句后面必须是函数调用语句
*/
func delay() {
defer fmt.Println("World")
fmt.Println("Hello")
}
/* 函数(使用小写的函数,是private的,使用大写的函数,是public的) */
func add(a, b int) int {
return a + b
}
/* 函数·多返回值*/
func swap(x, y string) (string, string) {
return x, y
}
8、结构体
结构体变量的成员可以通过点操作符访问:
结构体名称.变量名(user.name)
8.1结构体&Code
package main
import "fmt"
type user struct {
name string
password string
}
//检查传递的密码是否和储存在结构体中的密码相同
func (u user) checkPassword(password string) bool {
return u.password == password
}
func (u *user) restPassword(password string) {
u.password = password
}
func main() {
a := user{name: "wang", password: "1024"}
a.restPassword("2048") //更改密码
fmt.Println(a.checkPassword("2048"))
}
创建结构体定义变量指定类型,
Go语言的环境搭建
CSDN教程有很多输入关键词”使用VSCODE配置GO语言开发环境“即可
- pkgm 创建主函数
- for for语句
- forr for-range表达式 [集合、数组、切片、string、map]
- ff printf输出
- fp println输出
- git clone “ssh路径”//克隆文件到本地
- go mod init ”项目名“//生成mod文件[相当于项目模块]
- go build “文件名” //生成.exe文件
- ./main.exe //运行exe文件
- go test //开始测试
- go test -v //显示详细信息测试
- ctrl c //终端强制退出 再安装相应插件即可
Go语言项目实战
1、在线字典(Online dictionary)
1.1项目解析: 打开云彩小译在线翻译,右键检查——输入一个单词(good)——点击NetWork——点击Fetch/XHR——找到dict——右键Copy——点击Copy as URL(bash)——将拷贝内容复制到curl command中复制转化内容运行到编译器中,将输出结果拷贝到点击转换—嵌套得到结构体,再按如下Code操作
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
)
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
UserId string `json:"user_id"`
}
type DictResponse 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
fmt.Println("请输入你要查询的单词:")
fmt.Scanln(&word)
client := &http.Client{}
request := DictRequest{TransType: "en2zh", Source: word}
buf, err := json.Marshal(request)
if err != nil {
log.Fatal(err)
}
var data = bytes.NewReader(buf)
//创建请求
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
if err != nil {
log.Fatal(err)
}
//设置请求头
req.Header.Set("authority", "api.interpreter.caiyunai.com")
req.Header.Set("accept", "application/json, text/plain, */*")
req.Header.Set("accept-language", "zh-CN,zh;q=0.9")
req.Header.Set("app-name", "xy")
req.Header.Set("content-type", "application/json;charset=UTF-8")
req.Header.Set("device-id", "")
req.Header.Set("origin", "https://fanyi.caiyunapp.com")
req.Header.Set("os-type", "web")
req.Header.Set("os-version", "")
req.Header.Set("referer", "https://fanyi.caiyunapp.com/")
req.Header.Set("sec-ch-ua", `"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Windows"`)
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("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
// 发起请求
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close() //手动关闭流
// 读取响应
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
if resp.StatusCode != 200 {
log.Fatal("bad StatusCode", resp.StatusCode, "body", string(bodyText))
}
var dictResponse DictResponse
err = json.Unmarshal(bodyText, &dictResponse)
if err != nil {
log.Fatal(err)
}
// 最详细的结果打印整个结构体
// fmt.Printf("%#v\n", dictResponse)
fmt.Println("UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)
for _, item := range dictResponse.Dictionary.Explanations {
fmt.Println(item)
}
}