首页
About Me
推荐
weibo
github
Search
1
linuxea:gitlab-ci之docker镜像质量品质报告
49,451 阅读
2
linuxea:如何复现查看docker run参数命令
23,044 阅读
3
Graylog收集文件日志实例
18,580 阅读
4
linuxea:jenkins+pipeline+gitlab+ansible快速安装配置(1)
18,275 阅读
5
git+jenkins发布和回滚示例
18,181 阅读
ops
Openvpn
Sys Basics
rsync
Mail
NFS
Other
Network
HeartBeat
server 08
Code
Awk
Shell
Python
Golang
virtualization
KVM
Docker
openstack
Xen
kubernetes
kubernetes-cni
Service Mesh
Data
Mariadb
PostgreSQL
MongoDB
Redis
MQ
Ceph
TimescaleDB
kafka
surveillance system
zabbix
ELK Stack/logs
Open-Falcon
Prometheus
victoriaMetrics
Web
apache
Tomcat
Nginx
自动化
Puppet
Ansible
saltstack
Proxy
HAproxy
Lvs
varnish
更多
互联咨询
最后的净土
软件交付
持续集成
gitops
devops
登录
Search
标签搜索
kubernetes
docker
zabbix
Golang
mariadb
持续集成工具
白话容器
elk
linux基础
nginx
dockerfile
Gitlab-ci/cd
最后的净土
基础命令
gitops
jenkins
docker-compose
Istio
haproxy
saltstack
marksugar
累计撰写
690
篇文章
累计收到
139
条评论
首页
栏目
ops
Openvpn
Sys Basics
rsync
Mail
NFS
Other
Network
HeartBeat
server 08
Code
Awk
Shell
Python
Golang
virtualization
KVM
Docker
openstack
Xen
kubernetes
kubernetes-cni
Service Mesh
Data
Mariadb
PostgreSQL
MongoDB
Redis
MQ
Ceph
TimescaleDB
kafka
surveillance system
zabbix
ELK Stack/logs
Open-Falcon
Prometheus
victoriaMetrics
Web
apache
Tomcat
Nginx
自动化
Puppet
Ansible
saltstack
Proxy
HAproxy
Lvs
varnish
更多
互联咨询
最后的净土
软件交付
持续集成
gitops
devops
页面
About Me
推荐
weibo
github
搜索到
55
篇与
的结果
2020-11-23
linuxea:go错误处理和延迟执行(34)
go语言通过error接口实现错误处理的标准模式,在go中山没有异常的,可以通过返回值信息告诉调用者是否发生了错误。一般而言,我们需要定义返回错误的值,如果没有定义错误处理,那就会抛出错误信。1.错误处理errors.New()error接口通常error接口,通过errors包中的errors.New()和fmt.Errorf方法进行创建。errorerror如果没有错误就会返回nil,如果有就返回创建的错误信息我们先看没有错误处理的情景,比如下面这段代码:package main import "fmt" func division(a,b int) int { return a / b } func main(){ fmt.Println(division(9,3)) fmt.Println(division(1,0)) }运行[root@linuxea.com /opt/Golang/work3]# go run error1.go 3 panic: runtime error: integer divide by zero goroutine 1 [running]: main.division(...) /opt/Golang/work3/error1.go:4 main.main() /opt/Golang/work3/error1.go:8 +0x88 exit status 2errors.New()我们通过errors包中的errors.New()函数来创建我们定义返回值的错误类型,如下:首先判断,行参b等于0就返回-1,并且返回errors.New("division by zero")。反之返回a除以b,和nilfunc division(a,b int) (int,error) { if b == 0 { return -1,errors.New("division by zero") } return a / b,nil }在main函数中,也需要做处理,division函数中返回了两个返回值,main中接收,在做处理,如果返回的是nil,说明没有错误,直接打印返回的int,否则就将接收的errors返回值打印出来func main(){ fmt.Println(division(9,3)) if v,err := division(1,0);err != nil{ fmt.Println(err) }else { fmt.Println(v) } }代码块package main import ( "fmt" "errors" ) func division(a,b int) (int,error) { if b == 0 { return -1,errors.New("division by zero") } return a / b,nil } func main(){ fmt.Println(division(9,3)) if v,err := division(1,0);err != nil{ fmt.Println(err) }else { fmt.Println(v) } }运行[root@linuxea.com /opt/Golang/work3]# go run error.go 3 <nil> division by zerofmt.Errorf()除了errors.New还有在fmt包中的Errorf函数。我们打印下它的类型[root@linuxea.com /opt/Golang/work3]# cat error2.go package main import "fmt" func main(){ e := fmt.Errorf("Error: %s","division by zero") fmt.Printf("%T,%v\n",e,e) }运行[root@linuxea.com /opt/Golang/work3]# go run error2.go *errors.errorString,Error: division by zero2.延迟执行defer在很多时候,不管程序异常或者正常,我们都希望它执行一些代码。就需要延迟执行deferdefer会在函数退出的时候执行。示例打印两个语句,分别用defer和不用defer。如下:通常,defer会跟上一个匿名函数调用 defer func(){ fmt.Println("defer") }()我们在加上一个fmt.Println("main")package main import "fmt" func main(){ defer func(){ fmt.Println("defer") }() fmt.Println("main") } 运行[root@linuxea.com /opt/Golang/work3]# go run defer.go main defer可以发现,main先被打印,而后再打印的defer多个defer如果此刻有多个defer,打印的顺序将会是从后往前执行,如下:示例分别打印defer one,defer two和mainpackage main import "fmt" func main(){ defer func(){ fmt.Println("defer two") }() defer func(){ fmt.Println("defer one") }() fmt.Println("main") }运行[root@linuxea.com /opt/Golang/work3]# go run defer1.go main defer one defer two这遵循栈规则,先进后出。或者说defer是从下往上执行的顺序。3.panic与recover错误处理go语言提供panic和recover函数用于处理运行时的错误,当调用panic抛出错误,中断原有的流程控制,常用于不可修复性错误。recover函数用于终止错误处理流程,仅在defer语句的函数中有效,用于截取错误处理流程,recover只能捕获到最后一个错误panic示例我们在panic前后打印start和end[root@linuxea.com /opt/Golang/work3]# cat panic.go package main import "fmt" func main(){ fmt.Println("main start") panic("error") fmt.Println("main end") }运行[root@linuxea.com /opt/Golang/work3]# go run panic.go main start panic: error goroutine 1 [running]: main.main() /opt/Golang/work3/panic.go:5 +0x96 exit status 2可以看到panic后面的print是没有执行的。在panic处就结束了。recoverrecover函数一般用于做恢复的,主动处理panic的错误,必须用于defer中。但是和之前不同的是,使用了recover后,发生错误后返回的是一个panic error信息示例recover是string类型的一个error,所以我们可以使用if判断是否等于nil或者不等于nil如果不等于nil,那说明有错误,就可以抛出错误。这里手动加的panic("the is error")package main import "fmt" func main(){ defer func(){ if err := recover(); err != nil{ fmt.Println(err) } }() fmt.Println("start") panic("the is error") fmt.Println("end") }运行[root@linuxea.com /opt/Golang/work3]# go run recover.go start the is error如果没有panic错误,就不会执行recover()[root@linuxea.com /opt/Golang/work3]# cat recover.go package main import "fmt" func main(){ defer func(){ if err := recover(); err != nil{ fmt.Println(err) } }() fmt.Println("start") fmt.Println("end") }运行[root@linuxea.com /opt/Golang/work3]# go run recover.go start end示例2在其他函数中也可以直接这样抓取panic错误,如下:func test(){ defer func(){ if err := recover(); err != nil{ fmt.Println(err) } }() panic("the test error") }或者返回一个error信息首先定义一个error返回值,如果发生panic错误,就通过recover将值赋值给err,通过return返回func test() (err error) { defer func(){ if er := recover(); er != nil{ err = fmt.Errorf("%v",er) } }() panic("the test error") return }而后在main中,因为test有返回值,这里需要as接收,而后打印即可。func main(){ as := test() fmt.Println(as) }如下:package main import "fmt" func test() (err error) { defer func(){ if er := recover(); er != nil{ err = fmt.Errorf("%v",er) } }() panic("the test error") return } func main(){ as := test() fmt.Println(as) }运行[root@linuxea.com /opt/Golang/work3]# go run testerr.go the test error
2020年11月23日
2,449 阅读
0 评论
0 点赞
2020-11-17
linuxea:go函数闭包和类型引用与指针传递(33)
闭包通常指变量的生命周期,闭包指的是返回一个函数的时候用来外面的闭包。通常一个函数调用完成后是需要销毁的,但在被内部作用域引用的情况下,是不能进行销毁的。1.函数-闭包示例一般而言,在调用一个匿名函数的时候,通常如下: add30 := func(n int) int { return n + 30 }匿名函数赋值给add30,返回值是传递的行参加30.比如有多个,写多次 add30 := func(n int) int { return n + 30 } add20 := func(n int) int { return n + 20 } add10 := func(n int) int { return n + 10 } fmt.Println(add30(10)) fmt.Println(add20(10)) fmt.Println(add10(10))运行[root@linuxea.com /opt/Golang/work3]# go run add13.go 40 30 20现在,换种写法.定义一个addBase,在匿名函数中定义一个int类型的base行参,作为基数,返回一个int类型的函数类型。如下:addBase := func(base int) func(int) int {}而后在其中返回.首先返回值的类型是一个int的函数,那么就返回一个int类型的函数签名addBase := func(base int) func(int) int { return func(n int) int{ } }在返回的函数类型中,在return base + n addBase := func(base int) func(int) int { return func(n int) int{ return base + n } }在return base + n中,base是匿名函数中的基数的变量,return base + n返回的就是匿名函数的基数base函数+返回值中的n假如现在对addBase进行传参,比如传递一个实参,如8,addBase(8),这样就变成了, 8 +n,传递的8是base 赋值一个变量进行调用 add1 := addBase(8) fmt.Printf("%T\n",add1)add1现在也是一个函数类型。并且进行传值,而后打印 fmt.Println(add1(8))代码块package main import "fmt" func main(){ addBase := func(base int) func(int) int { return func(n int) int{ return base + n } } add1 := addBase(8) fmt.Printf("%T\n",add1) fmt.Println(add1(8)) }运行[root@linuxea.com /opt/Golang/work3]# go run add13.go func(int) int 16或者这样package main import "fmt" func main(){ addBase := func(base int) func(int) int { return func(n int) int{ return base + n } } fmt.Println(addBase(8)(8)) } 运行[root@linuxea.com /opt/Golang/work3]# go run add14.go 162.函数-值类型引用类型对于值类型和引用类型的区分,主要看变量赋值给新的变量后,修改新变量后如果对旧变量有影响,就是引用类型,如果没有影响就是值类型针对值类型和引用类型在赋值后新旧变量的地址并不相同,只是引用类型在底层共享数据结构(其中包含指针类型元素)值类型:int(数值),bool(布尔),float(浮点数),array,指针,数组,结构体引用类型:slice(切片),map(映射),接口等示例创建两个切片分别是array和slice,而后赋值给sliceA和arrayA,并且修改sliceA和arrayA的索引0位置的A修改成Z,而后打印结果package main import "fmt" func main(){ array := [3]string{"A","B","C"} slice := []string{"A","B","C"} arrayA := array sliceA := slice arrayA[0] = "Z" sliceA[0] = "Z" fmt.Println(arrayA,array) fmt.Println(sliceA,slice) }运行[root@linuxea.com /opt/Golang/work3]# go run add16.go [Z B C] [A B C] [Z B C] [Z B C]对于值类型,要修改需要通过指针来操作示例定义age,分别通过赋值修改,和指针操作来修改值。如下:package main import "fmt" func main(){ age := 30 ageA := age ageA = 31 fmt.Println(ageA,age) pointer := &age *pointer = 31 fmt.Println(*pointer,age) } 运行[root@linuxea.com /opt/Golang/work3]# go run add17.go 31 30 31 31最终指针修改会修改会影响到旧变量3.函数-值传递指针传递在go中只有值传递值传递在go语言中参数传递默认为值传递(形参为实参变量的副本),对于引用类型数据因其底层共享数据结构,所以在函数内可对引用类型数据修改从而影响函数外的原变量信息。如下图a赋值给b后,b是a复制的一份,而s1赋值给s2仍然共享底层数据指针传递指针赋值给函数后,将会指到原来的地址,并修改内存中的数据。变量的值也就变了。行参和实参都是通过拷贝的,只不过值的数据是一样的,但是值的地址指向是不一样的。示例值传递赋值的都是一个副本。引用类型数据因其底层共享数据结构。创建一个changeInt和changeSlice函数,分别是int类型,和切片,而后分别赋值不同的类型元素通过参数传递给函数,而后打印结果package main import "fmt" func changeInt(a int){ a = 100 } func changeSlice(s []int){ s[0] = 100 } func main(){ num := 1 changeInt(num) fmt.Println(num) nums := []int{1,2,3} changeSlice(nums) fmt.Println(nums) }运行[root@linuxea.com /opt/Golang/work3]# go run add18.go 1 [100 2 3]值类型传递并没有修改,说明changeInt修改没有影响,参数传递通过值类型传递给不同的地址。而引用类型传递后被修改,changeSlice修改完成,这些参数传递也是值类型传递,但是会指向同一一个内存区间。如果此时要修改值类型,就需要指针操作指针传递在原有的代码中添加一个changeIntByPoint函数func changeIntByPoint(a *int){}而后通过指针操作*a = 100如下:package main import "fmt" func changeInt(a int){ a = 100 } func changeSlice(s []int){ s[0] = 100 } func changeIntByPoint(a *int){ *a = 100 } func main(){ num := 1 changeInt(num) fmt.Println(num) nums := []int{1,2,3} changeSlice(nums) fmt.Println(nums) changeIntByPoint(&num) fmt.Println(num) }运行[root@linuxea.com /opt/Golang/work3]# go run add19.go 1 [100 2 3] 100现在值就变成了100
2020年11月17日
2,507 阅读
1 评论
0 点赞
2020-11-10
linuxea:go函数赋值传递和匿名函数(32)
函数也可以赋值给变量,存储在数组,切片,映射中,也可以作为参数传递给函数或作为函数返回值进行返回。函数的参数,数量,对应类型,以及函数返回值称为函数的签名。1函数赋值给变量示例:来看这样的示例.定义了add函数,而后在main中将add赋值给f,而后打印出add和f的类型package main import "fmt" func add(a,b int)int{ return a + b } func main(){ fmt.Printf("%T\n",add) f := add fmt.Printf("%T",f) }运行[root@LinuxEA /opt/Golang/work3]# go run add5.go func(int, int) int func(int, int) int当赋值后,f和add都是函数类型。只有相同的函数签名才能赋值,如果函数签名的类型不一样就不可以赋值package main import "fmt" func add(a,b int)int{ return a + b } func add1(a,b int,args ...string) int { return 0 } func main(){ fmt.Printf("%T\n",add) fmt.Printf("%T\n",add1) var f func(int,int) int = add1 fmt.Printf("%T",f) }运行[root@LinuxEA /opt/Golang/work3]# go run add6.go # command-line-arguments ./add6.go:13:6: cannot use add1 (type func(int, int, ...string) int) as type func(int, int) int in assignment1.2函数传递函数可以赋值给变量,那也就意味着可以能够进行作为实参进行传递。现在我们定义两个函数进行传参数。通过函数定义一个行参的函数类型,并把函数通过行参和实参进行传递。print函数先定义一个print函数,传递一个callback函数,func print(callback )callback函数用来格式化,将传递的数据按照每行打印,按|竖线分割打印。这里使用可变参数,这里之所以使用func(...string),是因为这里传递是一个函数,在print中的名称是callback。而对于print也是用一个 可变的string的行参。func print(callback func(...string),args ...string) {}这也就意味着callback可以接受任意多个字符串函数的变量。并且进行callback还需要进行解包callback(args...),如下:func print(callback func(...string),args ...string) { fmt.Println("println函数:") callback(args...) }list函数再定义一个相同函数签名的list函数func list(args ...string){}我们知道,相同函数签名是可以进行赋值的。并且对args进行遍历func list(args ...string){ for i,v := range args { fmt.Println(i,":",v) } }在main中进行调用func main(){ print(list,"A","C","E") }如下:package main import "fmt" func print(callback func(...string),args ...string) { fmt.Println("println函数:") callback(args...) } func list(args ...string){ for i,v := range args { fmt.Println(i,":",v) } } func main(){ print(list,"A","C","E") }当在main中的print函数中调用list的时候,list会传递给callback,而"A","C","E"会传递到print的args里面。callback在使用解包将"A","C","E"传递到list的args中进行遍历打印[root@LinuxEA /opt/Golang/work3]# go run add7.go println函数: 0 : A 1 : C 2 : E1.3匿名函数如果一个函数只使用了一次,就可以定义一个匿名函数。匿名函数直接定义一个函数的变量等于一个函数。示例定义一个匿名函数,行参名称是name,string类型,而后打印name,赋值给sayHello,如下: sayHello := func(name string) { fmt.Println("hello",name) }调用sayHello如下:sayHello("mark")代码块package main import "fmt" func main(){ sayHello := func(name string) { fmt.Println("hello",name) } sayHello("mark") }运行[root@LinuxEA /opt/Golang/work3]# go run add8.go hello mark示例2当然,我们也可以在定义的同时,直接使用。如下:func(name string) { fmt.Println("hello",name) }("mark")如下:package main import "fmt" func main(){ func(name string) { fmt.Println("hello",name) }("mark") }运行[root@LinuxEA /opt/Golang/work3]# go run add9.go hello mark示例3如下:package main import "fmt" func print(callback func(...string),args ...string) { fmt.Println("println函数:") callback(args...) } func list(args ...string){ for i,v := range args { fmt.Println(i,":",v) } } func main(){ print(list,"A","C","E") }将list函数写成匿名函数进行调用package main import "fmt" func print(callback func(...string),args ...string) { fmt.Println("println函数:") callback(args...) } func main(){ list := func(args ...string){ for i,v := range args { fmt.Println(i,":",v) } } print(list,"A","C","E") }运行[root@LinuxEA /opt/Golang/work3]# go run add10.go println函数: 0 : A 1 : C 2 : E甚至可以在进行修改在调用函数的时候使用匿名函数传递进去package main import "fmt" func print(callback func(...string),args ...string) { fmt.Println("println函数:") callback(args...) } func main(){ print(func(args ...string){ for i,v := range args { fmt.Println(i,":",v) } },"A","C","E") }运行[root@LinuxEA /opt/Golang/work3]# go run add11.go println函数: 0 : A 1 : C 2 : E
2020年11月10日
2,747 阅读
0 评论
0 点赞
2020-11-09
linuxea:go有参可变函数-返回值(31)
函数对代码进行复用。这和定义一个函数类似,不同的是是对代码块起一个名字,并且可以定义一些参数,这些参数可以进行传递和接收后进行处理 ,处理的结果也需要返回。可见,函数定义有:函数名,函数体,函数参数,返回值。1.函数go没有默认值,go的函数传递是非常简单,安装参数位置进行传递。其中,参数和返回值是可以有,也可以没有的。如果代码形式就成了下面这样func 函数名(函数参数) (返回值) {}函数参数(行参),是函数快的局部变量。行参返回值都需要描述参数类型和返回值的类型。如果行参配置后,也必须传入相应的值此前,使用的 fnuc main也是函数func main(){}函数也可以赋值给变量,存储在数组,切片,映射中,也可以作为参数传递给函数或作为函数返回值进行返回。函数的参数,数量,对应类型,以及函数返回值称为函数的签名。1.1无参数无返回值函数现在,简单写一个hello world.package main import "fmt" func sayHello(){ fmt.Println("Hello world!") }而后在main函数中调用,并打印类型func main(){ fmt.Printf("%T",sayHello) sayHello() }代码块package main import "fmt" func sayHello(){ fmt.Println("Hello world!") } func main(){ fmt.Printf("%T",sayHello) sayHello() }运行[root@LinuxEA /opt/Golang/work3]# go run func.go func()Hello world! Hello world!在main函数中可以调用多次sayHello函数package main import "fmt" func sayHello(){ fmt.Println("Hello world!") } func main(){ fmt.Printf("%T",sayHello) sayHello() sayHello() sayHello() sayHello() sayHello() }运行[root@LinuxEA /opt/Golang/work3]# go run func.go func()Hello world! Hello world! Hello world! Hello world! Hello world! Hello world!1.2有参数无返回值函数如上,在sayHello中加上参数name string。这里的参数也可以称为行参如果设置了多少个行参,也必须传入多个。func sayHello(name string){ fmt.Printf("Hello %s!",name) }name string是字符串类型,调用的时候也需要传入字符串.这里传入的是"mark"给sayHello,打印的时候打印的name就是mark。main函数中传递的参数也可以称为实参func main(){ sayHello("mark") }代码块[root@LinuxEA /opt/Golang/work3]# cat func2.go package main import "fmt" func sayHello(name string){ fmt.Printf("Hello %s!",name) } func main(){ sayHello("mark") }运行[root@LinuxEA /opt/Golang/work3]# go run func2.go Hello mark!或者也可以赋值传递 name := "sean" sayHello(name)代码块[root@LinuxEA /opt/Golang/work3]# cat func2.go package main import "fmt" func sayHello(name string){ fmt.Printf("Hello %s!",name) } func main(){ sayHello("mark") fmt.Println("\n") name := "sean" sayHello(name) }运行[root@LinuxEA /opt/Golang/work3]# go run func2.go Hello mark! Hello sean!1.3有返回值有参数函数写一个计算加法的函数,如下func add(a,b int)int{ return a + b }有俩个参数,分别是a和b,都是int类型,返回值也是Int类型。直接return行参即可在main函数中给add传入两个实参。并且需要一个值来接收。比如a。并且打印func main(){ a := add(1,2) fmt.Println(a) }也可以直接打印fmt.Println(add(1,2))代码块package main import "fmt" func add(a,b int)int{ return a + b } func main(){ a := add(1,2) fmt.Println(a) }运行[root@LinuxEA /opt/Golang/work3]# go run add.go 31.4可变参数可变参数也需要定义名称,参数类型使用...。三个点可变参数只能定义一个,并且一般只能定义在末尾定义a和b,而后定义可变参数args,可以有,也可以没有,使用三个点表示,而后写上类型,这里使用的是int,最后打印并返回一个0 .如下:并且打印出args类型:func addN(a,b int,args ...int) int { fmt.Println(a,b,args) fmt.Printf("%T",args) return 0 }在main中调用的时候,可以传入args,也可以不传func main(){ fmt.Println(addN(1,2)) fmt.Println(addN(1,2,3,4,5,6)) }运行[root@LinuxEA /opt/Golang/work3]# go run addn.go 1 2 [] []int0 1 2 [3 4 5 6] []int0可以看到,args的类型是一个切片。1.5计算可变参数值如上,现在将可变参数中的值进行相加,可变元素和a,b相加,args是切片。那么,现在通过遍历进行相加。首先,将a,b相加 titak := a + b而后遍历args切片,进行相加 for _,v := range args { titak += v }最后返回 return titak代码块[root@LinuxEA /opt/Golang/work3]# cat addn.go package main import "fmt" func addN(a,b int,args ...int) int { titak := a + b for _,v := range args { titak += v } return titak } func main(){ fmt.Println(addN(1,2)) fmt.Println(addN(1,2,3,4,5,6)) }运行[root@LinuxEA /opt/Golang/work3]# go run addn.go 3 211.6args函数中传递接上述的函数。现在创建一个cacl的函数,将addN的args传递进来。args默认是一个空切片,这时候就可以使用args的解包操作args...。解包的作用是将args从传递中进行解包(在本节案例中,解包后就是int类型),所以这里是有三个点,否则就变成了传递args元素。...操作只能在切片上如下:func cacl(op string,a,b int,args ...int) int { switch op { case "add": return addN(a,b,args...) } return -1 }而后在main函数中传递op字符串参数,a,b的int类型,args是可选参数。cacl("add",1,2):传递给cacl,第一个参数add,第二个1,1对于a,第二个2,2对应2。第三个参数没有,args为空切片。调用addN函数相加cacl("add",1,2,5):传递给cacl,第一个参数add,第二个1,1对于a,第二个2,2对应2。第三个参数是5,args解包切片中是5。调用addN函数相加cacl("add",1,2,5,8):传递给cacl,第一个参数add,第二个1,1对于a,第二个2,2对应2。第三个参数是5,args解包切片中是5。第四个参数是8,args解包切片中是8。调用addN函数相加如下:func main(){ fmt.Println(cacl("add",1,2)) fmt.Println(cacl("add",1,2,5)) fmt.Println(cacl("add",1,2,5,8)) }代码块[root@LinuxEA /opt/Golang/work3]# cat addn2.go package main import "fmt" func addN(a,b int,args ...int) int { titak := a + b for _,v := range args { titak += v } return titak } func cacl(op string,a,b int,args ...int) int { switch op { case "add": return addN(a,b,args...) } return -1 } func main(){ fmt.Println(cacl("add",1,2)) fmt.Println(cacl("add",1,2,5)) fmt.Println(cacl("add",1,2,5,8)) }运行[root@LinuxEA /opt/Golang/work3]# go run addn2.go 3 8 16除了以上的方式,在main函数中还可以修改,通过args的方式传入func main(){ args := []int{1,2,3,4,56,67} fmt.Println(addN(1,2,args...)) fmt.Println(cacl("add",1,2,args...)) }运行[root@LinuxEA /opt/Golang/work3]# go run addn2.go 136 1361.7解包删除切片如下:nums := []int{1,2,5,8,0}删除中间的5和之前的copy删除类型,用nums[:2],拿出索引start-2,在用nums[3:],拿出索引3到END。将nums[:2],nums[3:]...打印 fmt.Println("nums[:2]:",nums[:2]) fmt.Println("nums[3:]:",nums[3:])拿到的结果是[root@LinuxEA /opt/Golang/work3]# go run del.go nums[:2]: [1 2] nums[3:]: [8 0]加在一起就是1,2,8,0,而后使用append添加到nums中。这里必须用到nums[3:]...的解包。这是核心nums = append(nums[:2],nums[3:]...)代码块package main import "fmt" func main(){ nums := []int{1,2,5,8,0} nums = append(nums[:2],nums[3:]...) fmt.Println(nums) }运行[root@LinuxEA /opt/Golang/work3]# go run del.go [1 2 8 0]1.8返回值go中,函数所有的分支必须有返回值。在一个函数的逻辑中需要。在上述代码中return了-1,这里返回-1是因为返回值是int类型。如下:func cacl(op string,a,b int,args ...int) int { switch op { case "add": return addN(a,b,args...) } return -1 }return -1,-1在这里是说(只要是int类型就可以 ),不管有没有返回的结果,这里都会返回-1。因为在函数逻辑中这里是有返回值的。这似乎并不明了,写个简单的示例.执行两次 return 1 return 0并进行标注,看会发生什么package main import "fmt" func testReturn() int { fmt.Println("return 1 前") return 1 fmt.Println("return 1 后") return 0 } func main(){ fmt.Println(testReturn()) }运行[root@LinuxEA /opt/Golang/work3]# go run return.go return 1 前 1这里看到只是执行了return 1,这是因为代码执行到return后就不会在执行后面的了。而上述定义的return 2在执行了return 1后是永远都不会执行的。而在go中支持多个返回值。多返回值示例:cacl函数,有a和b两个行参,满足加减乘除。在go中,支持多个返回值,于是,代码就可以写成这样return a+b,a-b,a*b,a/b而return了四个返回值后,也需要4个类型来接收func calc(a,b int) (int,int,int,int) { return a+b,a-b,a*b,a/b }代码块package main import "fmt" func calc(a,b int) (int,int,int,int) { return a+b,a-b,a*b,a/b } func main(){ fmt.Println(calc(9,3)) }运行计算,a是9,b是3的加减乘除计算结果[root@LinuxEA /opt/Golang/work3]# go run calc.go 12 6 27 3当然,在main函数中,这里也可以分开传递,并且可以进行单个屏蔽,比如屏蔽a4,也就是除法,使用下划线即可。func main(){ a1,a2,a3,_ := calc(9,3) fmt.Println(a1,a2,a3) }运行[root@LinuxEA /opt/Golang/work3]# go run calc.go 12 6 27命名返回值上述的返回值是没有定义名称的,我们也可以定一个名称,定义名称后就可以直接return 返回值变量的最终结果返回。还是以加减乘除,如下:func calc2(a,b int) (sum int,diff int,product int,merchant int) { sum = a + b diff = a - b product = a * b merchant = a / b return }func main(){ fmt.Println(calc2(10,2)) }运行[root@LinuxEA /opt/Golang/work3]# go run calc2.go 12 8 20 5如果没有任何赋值就会返回0。命名返回值在代码量较多的时候查看和使用较为不便。1.9递归递归是指函数直接或间接调用自己,递归常用于解决分治问题,为相同的小问题进行解决,需要关注终止条件。计算0到100的和,用n的阶乘:f(n) 1...n0 - 100的和,等于0-99的和加上100,用函数表示就是f(99)+1000 - 99的和,等于0-98的和加上99,用函数表示就是f(98)+99函数就成了f(n) = n + f(n-1),而f(1) = 1的时候使用递归实现仍然计算一个1到100的和,假设是Addn的函数,返回值也是int.return的结果就是n + Addn(n-1)func Addn(n int) int{ return n + Addn(n-1) }计算0-5的和.func main(){ fmt.Println(Addn(5)) }这样就相当于从5开始计算Addn(5) => 5 + Addn(4) Addn(4) => 4 + Addn(3) Addn(3) => 3 + Addn(2) Addn(2) => 2 + Addn(1) Addn(1) = 1 + Addn(0)终止条件这样就会一直执行,递归会一直调用自己,形成了死循环。需要一个结束条件语句。当n等于1的时候就返回 if n == 1 { return 1 }如下:func Addn(n int) int{ if n == 1 { return 1 } return n + Addn(n-1) }这样代码执行完成package main import "fmt" func Addn(n int) int{ if n == 1 { return 1 } fmt.Println("计算f(n):",n) return n + Addn(n-1) } func main(){ fmt.Println(Addn(5)) }运行[root@LinuxEA /opt/Golang/work3]# go run add2.go 计算f(n): 5 计算f(n): 4 计算f(n): 3 计算f(n): 2 15
2020年11月09日
2,777 阅读
0 评论
0 点赞
2020-04-20
linuxea:go其他类型转换字符串(30)
Sprintf可以将其他类型转换成字符串1.1将int转换字符串Sprintf转换int到字符串,%dfmt.Sprintf("%d",12)代码块package main import ( "fmt" ) func main(){ a := fmt.Sprintf("%d",12) fmt.Println(a) fmt.Printf("%T",a) }运行[root@www.linuxea.com /opt/Golang/work2]# go run fmt.go 12 string1.2float浮点数转换为字符串Sprintf转换float到字符串,%ffmt.Sprintf("%f",12.2)代码块package main import ( "fmt" ) func main(){ a := fmt.Sprintf("%f",12.2) fmt.Println(a) fmt.Printf("%T",a) }运行[root@www.linuxea.com /opt/Golang/work2]# go run fmt2.go 12.200000 string1.3FormatBool布尔转换字符串将bool转换字符串strconv.FormatBool(false)代码块package main import ( "fmt" "strconv" ) func main(){ a := strconv.FormatBool(false) fmt.Printf("%T,%v",a,a) }运行[root@www.linuxea.com /opt/Golang/work2]# go run fmt3.go string,false1.4 Itoa将int类型转换为字符串将int类型转换为字符串 strconv.Itoa(123)代码块package main import ( "fmt" "strconv" ) func main(){ a := strconv.Itoa(123) fmt.Printf("%T,%v",a,a) }运行[root@www.linuxea.com /opt/Golang/work2]# go run fmt4.go string,1231.5 FormatInt进制类型转换字符串123转换10进制strconv.FormatInt(123,10)代码块package main import ( "fmt" "strconv" ) func main(){ a := strconv.FormatInt(123,10) fmt.Printf("%T,%v",a,a) }运行[root@www.linuxea.com /opt/Golang/work2]# go run fmt5.go string,123123转换16进制package main import ( "fmt" "strconv" ) func main(){ a := strconv.FormatInt(123,16) fmt.Printf("%T,%v",a,a) }[root@www.linuxea.com /opt/Golang/work2]# go run fmt5.go string,7b123转换8进制package main import ( "fmt" "strconv" ) func main(){ a := strconv.FormatInt(123,8) fmt.Printf("%T,%v",a,a) }[root@www.linuxea.com /opt/Golang/work2]# go run fmt5.go string,1731.6 FormatFloat转换字符串指定一个十进制或者科学记数法,‘E’是科学计数法,如果是转换10进制这里写'f',-1精度,64是float64类型strconv.FormatFloat(10.11,'E',-1,64)代码块package main import ( "fmt" "strconv" ) func main(){ a := strconv.FormatFloat(10.11,'E',-1,64) fmt.Printf("%T,%v",a,a) }运行[root@www.linuxea.com /opt/Golang/work2]# go run fmt5.go string,1.011E+01
2020年04月20日
3,575 阅读
0 评论
0 点赞
2020-04-16
linuxea:go字符串与其他类型的转换(29)
1.字符串与其他类型的转换转换bool,int1.1字符串转换Bool类型如下:strconv.ParseBool("true")会返回两个值,其中一个是err,接收两个值,如果err等于nil,说明没有错误,就打印v,如果有错误,就打印。如下:[root@www.linuxea.com /opt/Golang/work2]# cat strcov.go package main import ( "fmt" "strconv" ) func main(){ if v,err := strconv.ParseBool("true");err == nil { fmt.Println(v) } else { fmt.Println(err) } } 运行[root@www.linuxea.com /opt/Golang/work2]# go run strcov.go true1.2字符串转换int类型如下:strconv.Atoi("1024")会返回两个值,其中一个是err,接收两个值,如果err等于nil,说明没有错误,就打印v,如果有错误,就打印。如下:[root@www.linuxea.com /opt/Golang/work2]# cat strcov.go package main import ( "fmt" "strconv" ) func main(){ if v,err := strconv.Atoi("1024");err == nil{ fmt.Println(v) }else{ fmt.Println(err) } }运行[root@www.linuxea.com /opt/Golang/work2]# go run atoi.go 1024另外,使用strconv.ParseInt()也可以转换成int类型,但是需要指定转换的字节 if v,err := strconv.ParseInt("64",16,64);err == nil { fmt.Println(v) }else{ fmt.Println(err) }[root@www.linuxea.com /opt/Golang/work2]# go run atoi.go 10016*6+4=1001.3字符串转换float如下:strconv.ParseFloat("1.024",64)会返回两个值,其中一个是err,接收两个值,如果err等于nil,说明没有错误,就打印v,如果有错误,就打印。如下:package main import ( "fmt" "strconv" ) func main(){ if v,err := strconv.ParseFloat("1.024",64);err == nil{ fmt.Println(v) fmt.Printf("%T",v) }else{ fmt.Println(err) } }
2020年04月16日
2,770 阅读
0 评论
0 点赞
2020-02-04
linuxea:go字符串和字节(28)
8.字符串和字节字符串和字节切片区别bytes: 将buffer对象转换为字节切片String: 将buffer对象转化为字符串转换可以将string通过函数byte[]转化为字节切片,同时也可通过8.1strings包介绍strings包提供操作UFT-8字符串常用函数a).常用函数Compare: 比较字符串Contains:是否包含子字符串Count: 字符串出现次数EqualFold: 不区分大小写比较Fields: 按空白符分割字符串Split: 分割字符串为切片Join: 将字符串切片链接LastIndex: 获取字符串最后一次出现的位置Hasprefix: 是否以字符串作为某个字符串开头HasSuffix: 是否以字符串作为某个字符串结尾Index: 获取字符串首次出现等8.2strings常用操作比较字符串package main import ( "fmt" "strings" ) func main(){ fmt.Println(strings.Compare("abc","bac")) }不相等则是-1,否则是0[root@www.linuxea.com /opt/Golang/work2]# go run string.go -1是否包含某字符串abc是否包含bc,包含则为truefmt.Println(strings.Contains("abc","bc"))运行[root@www.linuxea.com /opt/Golang/work2]# go run string.go true只要包含一个字符就为tureabcdsadasdasdas只要包含一个b就为truefmt.Println(strings.Contains("abcdsadasdasdas","b"))[root@www.linuxea.com /opt/Golang/work2]# go run string.go true获取字符串出现的次数获取abcdsadasdasdas中a出现的次数fmt.Println(strings.Count("abcdsadasdasdas","a"))[root@www.linuxea.com /opt/Golang/work2]# go run string.go 5分割按空白字符分割 fmt.Println(strings.Fields("abc def\n eeee")) fmt.Printf("%q\n",strings.Fields("abc def\n eeee"))[root@www.linuxea.com /opt/Golang/work2]# go run string.go [abc def eeee] ["abc" "def" "eeee"]以什么结尾和开头HasPrefix是以什么开头,如果是就为trueHasSuffix是以什么结尾,如果是就为true fmt.Println(strings.HasPrefix("abcd","ab")) fmt.Println(strings.HasSuffix("abcd","cd"))[root@www.linuxea.com /opt/Golang/work2]# go run string.go true true索引位置cd在abcd中的索引位置,如果存在则打印索引位置,如果不存在就等于-1fmt.Println(strings.Index("abcd","cd"))[root@www.linuxea.com /opt/Golang/work2]# go run string.go 2这里还有Lastindex,就是最后出现的索引位置 fmt.Println(strings.LastIndex("abcdaasxcd","cd"))[root@www.linuxea.com /opt/Golang/work2]# go run string.go 8分隔符fmt.Println(strings.Split("adbcdef;abcd;abcd3edsa",";"))以;进行分割[root@www.linuxea.com /opt/Golang/work2]# go run string.go [adbcdef abcd abcd3edsa]连接符fmt.Println(strings.Join([]string{"adb","abcd","abcd3edsa"},"~"))以~进行链接[root@www.linuxea.com /opt/Golang/work2]# go run string.go adb~abcd~abcd3edsa重复N份fmt.Println(strings.Repeat("abc",3))将acb重复三次[root@www.linuxea.com /opt/Golang/work2]# go run string.go abcabcabc替换将abcabcabcabc中的a替换成1,1表示替换一次 fmt.Println(strings.Replace("abcabcabcabc","a","1",1))将abcabcabcabc中的a替换成1,-1表示全部替换 fmt.Println(strings.Replace("abcabcabcabc","a","1",-1))将abcabcabcabc中的a替换成1,ReplaceAll不需要指定替换多少次,默认替换全部 fmt.Println(strings.ReplaceAll("abcabcabcabc","a","1"))运行[root@www.linuxea.com /opt/Golang/work2]# go run string.go 1bcabcabcabc 1bc1bc1bc1bc 1bc1bc1bc1bc大小写转换ToLower转换小写,ToUpper转换大写 fmt.Println(strings.ToLower("abcABC")) fmt.Println(strings.ToUpper("abcABC"))运行[root@www.linuxea.com /opt/Golang/work2]# go run string.go abcabc ABCABC首字母大写fmt.Println(strings.Title("hello"))将hello首字母大写[root@www.linuxea.com /opt/Golang/work2]# go run string.go Hello前后字符去掉fmt.Println(strings.Trim("xhelloxz","xz"))去掉xhelloxz前后包括xz或者前后包含x,z的字符[root@www.linuxea.com /opt/Golang/work2]# go run string.go hello去除空白字符fmt.Println(strings.TrimSpace(" hello \n \r "))[root@www.linuxea.com /opt/Golang/work2]# go run string.go hello8.3定义字节切片byte是无符号的uint8类型。package main import ( "fmt" ) func main(){ var bytes []byte = []byte{'a','b','c'} fmt.Printf("%T,%#v\n",bytes,bytes) }[root@www.linuxea.com /opt/Golang/work2]# go run byte.go []uint8,[]byte{0x61, 0x62, 0x63}这里a,b,c的ASCII分别是0x61, 0x62, 0x638.4字节转换字符串直接使用string转换即可package main import ( "fmt" ) func main(){ var bytes []byte = []byte{'a','b','c'} fmt.Printf("%T,%#v\n",bytes,bytes) sb := string(bytes) fmt.Printf("%T %v\n",sb,sb) }将定义的bytes转换成字符串[root@www.linuxea.com /opt/Golang/work2]# go run byte.go []uint8,[]byte{0x61, 0x62, 0x63} string abc8.5字符串转字节将转换过的字符串再转回字节package main import ( "fmt" ) func main(){ var bytes []byte = []byte{'a','b','c'} fmt.Printf("%T,%#v\n",bytes,bytes) sb := string(bytes) fmt.Printf("%T %v\n",sb,sb) bs := []byte(sb) fmt.Printf("%T %#v\n",bs,bs) }如下[root@www.linuxea.com /opt/Golang/work2]# go run byte.go []uint8,[]byte{0x61, 0x62, 0x63} string abc []uint8 []byte{0x61, 0x62, 0x63}8.6bytes包bytes包与strings包基本上一样Compare 比较按照直接数组进行比较fmt.Println(bytes.Compare([]byte("abc"),[]byte("def")))运行[root@www.linuxea.com /opt/Golang/work2]# go run byte.go -1Index索引位置bytes.Index索引位置计算字节def在abcdef的索引位置fmt.Println(bytes.Index([]byte("abcdef"),[]byte("def")))运行[root@www.linuxea.com /opt/Golang/work2]# go run byte.go 3bytes.Contains字节abcdef是否包含def,如果包含则为true,否则falsefmt.Println(bytes.Contains([]byte("abcdef"),[]byte("def")))运行[root@www.linuxea.com /opt/Golang/work2]# go run byte.go true8.7计算unicode当使用len计算字符串是可以的,但是遇到中文字符就需要unicode/utf8模块计算。如下:[root@www.linuxea.com /opt/Golang/work2]# cat byte1.go package main import ( "fmt" "unicode/utf8" ) func main(){ s := "这是一个测试" fmt.Println(s) fmt.Println(utf8.RuneCountInString(s)) }运行[root@www.linuxea.com /opt/Golang/work2]# go run byte1.go 这是一个测试 6
2020年02月04日
2,494 阅读
1 评论
0 点赞
1
2
3
...
8