这篇文章的由来是这样的,我在看了项目代码之后发现真的一点也看不懂是的没错!看不懂。所以打算从小项目开始自己尝试敲代码。当然敲代码会出错,出错就要问。问完之后,就发现自己基础不扎实!
所以我决定二刷Go by Example ,会很细致的刷一遍,让后多敲一敲代码,也就是说这遍会结合代码来刷。还是老样子使用的goland,如何做好打代码的准备,请开我之前的那个文章
总之,基础很重要不要着急,慢慢来吧。这里也会把自己练手的拓展项目简单记录一下,分N篇~(看我懒不懒吧)
看这个文章的小秃头们,建议结合一个GO by Example来看,因为我这个就是一个笔记,结合着看你就会明白啦[值得开心的是~~我终于会插入代码了]
1.Hello World:
(1)创建main.go可以放在main的文件夹下,也可以直接创建main.go在你的gopath下。都可以编译
(2)fmt是打印,需要导入fmt的包
2.值
(1)这里
fmt.Println("7.0/3.0 =", 7.0/3.0)也可以为7/3.0 ,但是一旦赋值给变量如下:
f:=3.0//声明赋值变量下面会学
a:=4
fmt.Print(f/a) //报错因为两个类型不同
3.变量
(1)值得注意的是:声明后没有给初始值,变量变成对应的0值 (bool类型的零值为false)
4.常量
(1)声明的常量在main之外作用全局
(2)声明常量的语法和变量不同:const 常量名 = 值
(3)常量之间可以进行运算,常量和变量也可以,还是来个栗子好表达
const n =5
const m =10.0
//h:=true 这个跟啥都不行别想了
fmt.Print(m/n) //正常输出 2
f:=10.00
fmt.Println(f/n) //正常输出 2,而不是2.0
fmt.Println(math.Sin(n)) //常量ok,可以根据需要进行改变,正常输出
ff:=10
fmt.Println(math.Sin(ff)) //变量不行,报错!类型不对
5.For 循环
这里说一下return和break的区别哈,break是跳出循环,return是跳出方法,来吃栗子~
for {
fmt.Print("1")
return
}
fmt.Println("2") //输出结果为1
for {
fmt.Print("1")
break
}
fmt.Println("2") //输出结果为12
6.If/Else 分支
go没有三目运算符,三目运算符是什么呢,来吃个栗子
a>0?a=1:a=0 //若a>0则让a=1,否则a=0,当然go不支持这个!
7.Switch 分支结构
在这里面看到许多关于时间的来说一下,时间需要导入time包,当然goland会帮你自动导入
你所看到的Hour()、Weekday()、Second()这类方法都是在Time.now获取完当下时间的情况写才会适用,如果Time.Hour只会输出1h0m0s,吃个栗子~(现在时间为10.07)
fmt.Println(time.Now().Hour()) //输出10
fmt.Print(time.Hour) //输出1h0m0s
下面来一个自己练习的小代码——将24时改为12时
t:=time.Now()
switch t.Weekday() {
case time.Saturday,time.Sunday:
fmt.Println("休息日:")
default:
fmt.Println("工作日")
}
switch {
case t.Hour()>12:
fmt.Println("下午:",t.Hour()-12,"点",t.Minute(),"分",t.Second(),"秒")
default:
fmt.Println("上午:",t.Hour(),"点",t.Minute(),"分",t.Second(),"秒")
}
(type switch)我觉得这个用法有点怪,对于我来说就是新的东西,让后多写写这里也直接copy过来
whatAmI :=func(i interface{}) {
switch t :=i.(type) {
case bool:
fmt.Println("I'm a bool")
case int:
fmt.Println("I'm an int")
default:
fmt.Printf("Don't know type %T\n",t)
}
}
whatAmI(true)
whatAmI(1)
whatAmI("hey")
8.数组
(1)数组初始化
var b [2]int = [2]int{1,2}//普通的初始化
fmt.Println(b)
a:= [5]int{1,2,3,4,5}//我喜欢的初始化
fmt.Println(a)
c:=[...]int{1,2,3}//不确定长度的初始化
fmt.Println(c)
(2)数组取值(数组设值类似)
a:= [5]int{1,2,3,4,5}
fmt.Println(a) //输出结果:[1,2,3,4,5]
fmt.Println(a[0]) //输出结果:1
fmt.Println(len(a)) //输出结果:5(数组长度)
9.切片
s:=make([]string,3)
s[0]="I"
s[1]="♥"
s[2]="U"
fmt.Print(s)
s =append(s,"meng","yu")
b:=make([]string,9)//如果不够长可以copy但是copy不完全
copy(b,s)
fmt.Println(b[:2])//真实范围为[能取到,不能取到)
10.Map
s:=make(map[string]int)
s["k1"]=1
s["k2"]=2
fmt.Println(s)
h:=map[string]int{"h1":1,"h2":2}//声明并初始化
fmt.Println(h)
a:=s["k1"]
b:=len(s)//长度
delete(s,"k1")//删除一个
_,c:=s["k2"]//检查k1是否存在
fmt.Println(a,b,c)
11.Range 遍历
s:=map[string]int{"k1":1,"k2":2,"k3":3,"k4":4,"k5":5}
sum1,sum2:=0,0
for _,ss:=range s{//求和
sum1+=ss
}
fmt.Println(sum1)
for k,_:=range s{//求和
sum2+=s[k]
}
fmt.Println(sum2)
m:=map[string]string{"a":"aa","b":"bb"}
for i,j:=range m{
fmt.Println(i,"->",j)
}
for g,l:=range "go"{//迭代Unicode码点
fmt.Println(g,l)//第一个g:返回字符的起始字节位置
//第二个l:字符本身
}
12.函数
(1)外部函数
func plus(b,c int) int {
return b+c
}
func main() {
c:=plus(1,2)
fmt.Print(c)
}
(1)内部函数
func main() {
f:=func(a,b int)int {
return a+b
}
c:=f(1,2)
fmt.Print(c)
}
13.多返回值
func a() (int,int) {//返回值类型相同
return 10,1
}
func b() (int,float32) {//返回值类型不同
return 1,1.01
}
func main(){
m,n:=a()//一次性给两个变量赋值
i,j:=b()//同上
_,c:=b()//可以用“_”来只要一个返回值
fmt.Print(m,n)
fmt.Println(i,j)
fmt.Println(c)
}
14.变参函数
func sum(nums...int) {
fmt.Print(nums," ")
t:=0
for _,num:=range nums{
t +=num
}
fmt.Printf("%d\n",t) //格式化输出,不能直接在括号里面写t
}
func main(){
sum(1,2,3)//可以是三个值
sum(1,2,3,4)//也可以是四个值
nums:=[]int{1,2,3,4,5}//也可以是数组
sum(nums...)
}
15.闭包
他返回值是一个没有名字的函数
他的作用就是:缩小变量作用域,减少对全局变量的污染
func add()func(int)int{
sum:=0
return func(i int)int {
sum+=i;
return sum
}
}
func main(){
myadd:=add()
for i:=1;i<=10;i++ {
myadd(i)
}
fmt.Println(myadd(0))
fmt.Println(myadd(45))
}
16.递归
这个就是联系联系,写一个阶乘运算吧
func f(a int)int {
if a ==0 {
return 1
}
return a *f(a-1)
}
func main(){
fmt.Print(f(4))
}
17.指针
func zhi(z int) {
z=0
}
func dizhi(dz *int) {
*dz=0
}
func main(){
i:=1
fmt.Println(i) //直接输出1
zhi(i) //调用普通的函数,无返回值所以i不改变
fmt.Println(i) //输出1
dizhi(&i) //传入i的地址,改变i的地址(指向数字0)
fmt.Println(i)//再输出i的时候,值改变为0
fmt.Println(&i)//输出i的地址为数字0的地址
}
18.结构体
type user struct {
id int
name string
age int
}
func main() {
u:=user{1,"mengyu",22}//声明并初始化一个结构体
fmt.Println(u)
u.age=18 //通过“.“改变结构体中字段的数据
fmt.Println(u)
m:=user{name:"mengyu"}//只赋值部分的字段,其余字段为0值
fmt.Println(m)
s:=&m //生成结构体指针,依旧可以正常使用
fmt.Println(s.name)
}
把属于该结构体的方法写在结构体的下面,来~吃个栗子
type user struct {
id int
name string
age int
}
func main(){
ss:=user{}
ss.sget()
fmt.Print(ss)
}
func (this *user)sget()user {//从键盘获取结构体use的值
fmt.Scanln(&this.id)
fmt.Scanln(&this.name)
fmt.Scanln(&this.age)
return user{}
}
19.方法
上面写了。。。。嗯。。。。
再来巩固一下,这里说一下函数和方法的区别(想当初我真觉的没啥区别)
方法:func (接收器变量 接收器类型) 方法名(传入的参数)(返回的参数类型){}
//这里面的接收器不太好理解,大概就是说谁可以用这个函数,这个谁就是接收器,这个接收器基本上就是上面你创建的结构体,结构体下面就写这些方法
函数:func 函数名 (传入的参数)(返回的参数类型){}
type squle struct {
w int //宽
c int/ //长
h int //高
}
func main(){
r:=squle{10,20,30}
fmt.Println(r.mianji())
fmt.Println(r.tiji())
rp:=&r //想要避免在调用方法时产生一个拷贝,或者想让方法可以修改接受结构体的值, 你都可以使用指针来调用方法。
fmt.Println(rp.tiji())
fmt.Println(rp.mianji())
}
func (this *squle)mianji()(int){
return this.w*this.c
}
func (this *squle)tiji()(int){
return this.w*this.c*this.h
}
20.接口
type squle struct {
c int
k int
g int
}
type smath interface {//说明squle的接口
mianji()int
tiji()int
}
func jkshixian(s smath) {//通过这个方法实现接口
fmt.Println(s.tiji())
fmt.Println(s.mianji())
}
func (this squle)mianji()(int) {//方法实现
return this.c*this.k
}
func (this squle)tiji()(int) {//方法实现
return this.c*this.k*this.g
}
func main() {
s:=squle{10,20,30}
jkshixian(s)
}
网友评论