设计网页作业,seo如何优化网站推广,dede 建设网站,北京关键词优化服务本文章主要是写自己在做这个项目时候遇到的一些困难#xff0c;如果都是做这个项目的#xff08;后端#xff09;#xff0c;可以看看
这个是项目网址
gin-vue-admin : https://github.com/flipped-aurora/gin-vue-admin
在此表示对大神奇淼的敬佩
首先#xff0c;我们…本文章主要是写自己在做这个项目时候遇到的一些困难如果都是做这个项目的后端可以看看
这个是项目网址
gin-vue-admin : https://github.com/flipped-aurora/gin-vue-admin
在此表示对大神奇淼的敬佩
首先我们需要去下载一个cnpm的一个东西
我是看这个博客写的贼好
npm和cnpmwindows安装步骤_安装cnpm-CSDN博客
然后就去vs里面执行了我还以为没执行成功把终端输出的东西给chatgpt看了一下显示成功了
然后我进入了这个server项目嘛但是之前的go感觉有些要补一下就先开始了视频教程里面的golang教程选择性学语言就是这样的学了又忘
学习就是一个重复的过程在做项目的时候有时候会对自己产生怀疑呜呜呜
回忆一下
一定要以go.mod为根目录
var a string hello 2002
//关键字 变量名 变量类型 变量值
/*
关键字不能作为变量名
*/
//注意大写字母表示可以被其他包访问
//改变包的名称
cool goclass/pkg //将包名改成cool
/*
将一个包名完全引入
*/
. goclass/pkg
//这样子我们可以访问一个包中的私有属性基本数据类型
整数类型
我们一般直接使用uint 和int类型如果你的电脑是64位就会变成int64,如果是32就会使int32.
uint只能是正数
浮点类型 float64(一般使用这个) float32
后面跟的是精确度就是小数点后面有几个数
只要类型不同就会直接报错
怎么判断是什么类型
var str string
str Im a string
fmt.Printf(%T,str)数据类型的转化→使用一个包 strconv
package mainimport (fmtstrconv
)func main() {var str stringstr Im a stringfmt.Printf(%T\n, str)num, _ : strconv.Atoi(str)fmt.Printf(转换str之后%T\n, num)num2 : 456str strconv.Itoa(num2)fmt.Printf(%T\n, str)str 3.14f, _ : strconv.ParseFloat(str, 64)fmt.Printf(%T\n, f)f 2.731str strconv.FormatFloat(f, E, -1, 64)fmt.Printf(%T\n, str)str trueb, _ : strconv.ParseBool(str)fmt.Printf(%T\n,b)}听视频复习的感觉跟第一遍学的时候完全 不一样啊
复杂数据类型
不能以数字特殊标记开头
流程控制语句
a:0
//没有前增 a / --a
//只有后增后减
a
a--func main() {a : 1switch a {case 1:fmt.Println(a)fallthrough/*注意fallthrough并不会执行case2的判断语句*/case 2:fmt.Println(fallthrough之后的结果)default:fmt.Println(都不成立)}}/*
以前我一直觉得死循环没用直到我刷了几个算法题
*/
/*
好的又复习到一个不记得的
continue是跳出本次循环
*/
a:0
for a10{aif (a5){continue}fmt.Println(a)//不会输出5
}//goto
//还有这个wqfunc main() {a : 1
A: //之前可能阅读那个书籍的时候没有彻底阅读流程部分for a 10 {aif a 5 {break Agoto B}fmt.Println(a)//不会输出5}
B:fmt.Println(我来到B了)}数组把同一类元素放在一起的集合
a : [3]int{1, 2, 3}
//[元素长度]元素类型{元素1元素2...}fmt.Println(a)a : [3]int{1, 2, 3}fmt.Println(a)
//当我们不知道有多少个数的时候
b : [...]int{2423, 4, 3, 43, 4, 3, 4, 3, 43, 4}
//直到需要多杀个数但是不知道具体值的时候var d new([10]int)d[5] 3fmt.Println(a, b, d)
//注意打印d的时候会含有
//因为使用new创建的是一个指针对同一类东西做同一个操作的时候会很方便
len(数组) cap(数组)
a : [3]int{1,2,3}
cl : a[:]
cl a[1:]package mainimport fmtfunc main() {//数组的len和cap是一样的但是切片不是a : [3]int{1, 2, 3}cl : a[:]fmt.Println(初始len and cap, len(cl), cap(cl))cl append(cl, 5)fmt.Println(len(cl), cap(cl))cl append(cl, 5)cl append(cl, 5)cl append(cl, 5)cl append(cl, 5)fmt.Println(len(cl), cap(cl)) //cap到达一定的值会自动扩充到某个值//这里了解即可
}//数组的len和cap是一样的但是切片不是a : [3]int{1, 2, 3}cl : a[:]//讨论copy/*将后面的某一段复制到前面的一段如果没有特定标记就是从0开始*/cl1 : a[1:]copy(cl, cl1)fmt.Println(cl) //expect 233a : [3]int{1, 2, 3}cl : a[:]//讨论copy/*如果说我们后面copy的数组len超过了前面的len,就会直接覆盖*/cl1 : append(cl, 5)cl1 append(cl1, 5)copy(cl, cl1)fmt.Println(cl1)package mainimport fmtfunc main() {//数组的len和cap是一样的但是切片不是a : [3]int{1, 2, 3}cl : a[:]//讨论copy/*如果我们想要指定覆盖*/cl1 : a[2:]copy(cl[1:2], cl1)fmt.Println(cl)
}//创造切片的方式
var aa []int//空数组aa : append(aa,5)aaa : make([]int,4) //有默认值map
package mainimport fmtfunc main() {/*三种声明方式*/var m map[string]stringm map[string]string{}m[name] xzcm[sex] 男m2 : map[int]bool{}m2[1] truem2[2] falsem3 : make(map[string]string)m3[sex] 女m4 : map[int]interface{}{} //规定入参结构和出参结构就行m4[1] 1m4[2] falsem4[3] xzcfmt.Println(m4)//delete(变量名key)delete(m4, 1)fmt.Println(m4)//当前长度fmt.Println(m[sex])//通过for range 找到它的for k, v : range m4 {fmt.Println(k, v)}
}func
func 函数名(入参1 入参类型入参2 入参类型(出参1 出参类型出参2 出参类型)package mainpackage mainimport fmt/*func bb(data1 string) {fmt.Println(data1)}
*/
func main() {b : func(data1 string) {fmt.Println(data1)}/*大概就是b : bb*/b(Fuck)mo(1, 2, 23, 32)a : []string{2, 3, 4, 5}//将切片传入mo(2, a...)
}// 不知道入参有多少个这样的我们成为不定项参数一定要放在最后一个
func mo(data1 int, data2 ...string) {fmt.Println(data2)for k, v : range data2 {fmt.Println(k, v)}
}func A(data1, data2 int) (res1 string, res2 int) {//我们没有在函数内部定义res1 和 res2/*但是Go会自动帮助我们var ret1 stringvar res2 int*/return //省略 return res1,res2
}func main() {//延迟调用函数defer last()//自知型函数//自动执行(func() {fmt.Println(我在这里执行别人都管不着)})()mo()(4)
}// 闭包函数
func mo() func(int) {return func(num int) {fmt.Println(成功声明闭包函数, num)} //返回的要和回参一毛一样
}
func last() {fmt.Println(我要最后执行)
}指针和地址
package mainimport fmtfunc main() {var a inta 123fmt.Println(a)var b *int/*b a指针不能指向数据只能指向具体值的地址*/b a // 内存地址fmt.Println(a, *b)*b 456 //*内存地址fmt.Println(a, *b)}package mainimport fmtfunc main() {//数组指针var a [5]stringa [5]string{1, 2, 3, 4, 5}var aP *[5]stringaP afmt.Println(a, aP)//指针数组var arrP [5]*stringstr1 : str1str2 : str2str3 : str3str4 : str4str5 : str5arrP [5]*string{str1, str2, str3, str4, str5}for k, v : range arrP {fmt.Println(k, *v)}*arrP[3] 333 //修改指针fmt.Println(str4)
}package mainimport fmtfunc main() {var str1 我定义了pointFunc(str1)//指针传参fmt.Println(str1)
}func pointFunc(p1 *string) {*p1 我变了
}在map当中我们通常不需要设置指针map本身就是引用类型
struct
结构体是一个可以存储不同数据类型的数据类型
package mainimport fmttype Qm struct {Name stringSex stringHobbies []string
}func main() {/*三种声明方式var qm Qmqm.Name qmqm.Sex 男qm.Hobbies []string{唱歌, 打游戏}*//*qm : Qm{xzc, 男, []string{打游戏},}*///建议用这种方法qm : Qm{Name: xzc,Sex: 男,Hobbies: []string{11223, 342},}qmFunc(qm)/*qm : new(Qm)//声明了一个Qm的空结构体类似于java实例fmt.Println(qm)*/}func qmFunc(qm Qm) {fmt.Println(qm)
}qm : Qm{Name: xzc,Sex: 男,Hobbies: []string{11223, 342},}qmPtr : qm.Name*qmPtr zcx //会被看成*(qmPtr.Name),但实际上qmPtr是指向的qmfmt.Println(qm)qmPtr2 : qm(*qmPtr2).Name zcx2fmt.Println(qm)结构体可以有自己的方法
package mainimport fmttype Qm struct {Name stringSex stringHobbies []stringHome //复制进来直接归属Qm
}type Home struct {P string
}func (h *Home) Open() {fmt.Println(open the, h.P)
}
func (q *Qm) Song(name string) (restr string) {fmt.Printf(%s唱了一首%v, q.Name, name)return 观众觉得很好听
}
func main() {qm : Qm{Name: xzc,Sex: 男,Hobbies: []string{11223, 342},}qmPtr : qm.Name*qmPtr zcx //会被看成*(qmPtr.Name),但实际上qmPtr是指向的qmfmt.Println(qm)qmPtr2 : qm(*qmPtr2).Name zcx2fmt.Println(qm)restr : qm.Song(惊雷)fmt.Print(restr)qm.P 北京fmt.Println(qm)qm.Open() //连他的方法都可以用
}interface 接口
是一系列方法的集合是一个规范
/* var a Animalc : Cat{Name: Tome,Sex: 男,}a ca.Eat()a.Run()*/var a Animala Cat{Name: Tome,Sex: 男,}a.Eat()a.Run()package mainimport fmttype Animal interface {Eat()Run()
}type Cat struct {Name stringSex string
}type Dog struct {Name string
}// Cat is an animal
func (c Cat) Run() {fmt.Println(c.Name, 开始跑)
}func (c Cat) Eat() {fmt.Println(c.Name, 开始吃)
}
func (c Dog) Run() {fmt.Println(c.Name, 开始跑)
}func (c Dog) Eat() {fmt.Println(c.Name, 开始吃)
}
func main() {c : Dog{Name: spake}Myfunc(c)
}func Myfunc(a Animal) {//这就是泛型a.Eat()a.Run()
}package mainimport fmttype Animal interface {Eat()Run()
}type Cat struct {Name stringSex bool
}type Dog struct {Name string
}// Cat is an animal
func (c Cat) Run() {fmt.Println(c.Name, 开始跑)
}func (c Cat) Eat() {fmt.Println(c.Name, 开始吃)
}
func (c Dog) Run() {fmt.Println(c.Name, 开始跑)
}func (c Dog) Eat() {fmt.Println(c.Name, 开始吃)
}var L Animalfunc main() {c : Cat{Name: Tom,Sex: true,}Myfunc(c)L.Run()}
func Myfunc(a Animal) {L a
}goroutine and channel
Goroutine 是 Go 语言中的一种轻量级线程它可以在相同的地址空间中并发执行多个函数。Goroutine 的创建和调度由 Go 运行时系统自动管理不需要用户手动进行线程管理。
package mainimport (fmtsync
)func main() {var wg sync.WaitGroupwg.Add(1) //协程管理器go Run(wg)wg.Wait()
}func Run(wg *sync.WaitGroup) {fmt.Println(我跑起来了)wg.Done()
}package mainimport fmtfunc main() {c1 : make(chan int)c1 - 1fmt.Println(-c1) //这里会被阻塞因为c1没有缓冲区无法存放1// 但是-c1表示我需要从c1管道中找到一个值
}package mainimport fmtfunc main() {c1 : make(chan int, 5)go func() {for i : 0; i 10; i {c1 - i //先会存5个被取了之后立马存}}()for i : 0; i 10; i {fmt.Println(-c1)} /*这里其实是等待c1通道发送消息过来*/
}package mainimport fmtfunc main() {c1 : make(chan int, 5)/*var read -chan int c1var write chan- int c1close(c1)*/c1 - 1c1 - 2c1 - 3c1 - 4c1 - 5close(c1)for v : range c1 {fmt.Println(v)//如果不关闭通道接收方会一直读取}}package mainimport fmtfunc main() {ch1 : make(chan int, 1)ch2 : make(chan int, 1)ch3 : make(chan int, 1)ch1 - 1ch2 - 2ch3 - 3select { //随机执行case -ch1:fmt.Println(ch1)case -ch2:fmt.Println(ch2)case -ch3:fmt.Println(ch3)default:fmt.Println(都不满足)}}package mainimport fmtfunc main() {c : make(chan int)var read -chan int cvar write chan- int cgo SetChan(write)GetChan(read)
}
func SetChan(write chan- int) {for i : 0; i 10; i {fmt.Println(我是在write函数中)write - i}
}
func GetChan(read -chan int) {for i : 0; i 10; i {fmt.Println(我从chan中取出, -read)}
}断言和反射
断言把一个接口类型调用为原始结构并且可以使用原始结构的方法和属性
package mainimport fmttype User struct {Name stringAge intSex bool
}
type Student struct {UserClass string
}func (u User) SayName(name string) {fmt.Println(我的名字叫做, name)
}
func main() {u : User{许智超,18,true,}check(u)//人为我们已经知道传入的是User
}
func check(v interface{}) {switch v.(type) {case User:fmt.Println(v.(User).Name)fmt.Println(我是User)case Student:v.(Student).SayName(v.(Student).Class)fmt.Println(我是Student)}//我们这些很麻烦//反射应运而生不需要使用switch//可以直接知道它的类型
}func check(inter interface{}) {t : reflect.TypeOf(inter) //类型v : reflect.ValueOf(inter) //所有值for i : 0; i t.NumField(); i {//NumField是指结构体中有几个值fmt.Println(v.Field(i))}fmt.Println(t, v)
}func check(inter interface{}) {v : reflect.ValueOf(inter) //所有值fmt.Println(v.FieldByName(Class))
}package mainimport (fmtreflect
)type User struct {Name stringAge intSex bool
}
type Student struct {UserClass string
}func (u User) SayName(name string) {fmt.Println(我的名字叫做, name)
}
func main() {u : User{许智超,18,true,}s : Student{u, 三年二班}check(s)fmt.Println(s)//人为我们已经知道传入的是User
}
func check(inter interface{}) {v : reflect.ValueOf(inter)e : v.Elem()//要使用下面的需要传入指针e.FieldByName(Class).SetString(四年二班)fmt.Println(inter)
}package mainimport (fmtreflect
)type User struct {Name stringAge intSex bool
}
type Student struct {UserClass string
}func (u User) SayName(name string) {fmt.Println(我的名字叫做, name)
}
func main() {u : User{许智超,18,true,}check(u)
}
func check(inter interface{}) {v : reflect.ValueOf(inter)m : v.Method(0)m.Call([]reflect.Value{reflect.ValueOf(大牛逼)})
}day 2从Mutex继续开始