在《基础篇》和《入门篇》当中,我们已经知道了Golang的基本属性、方法等知识,接下来,在本文当中就详细介绍一下Go中的一些常用操作和语法函数,包含下面几个内容。相信阅读完后续章节的朋友,就能大致对Go语言的项目开发有了一个基础的掌握。
为响应交流的朋友反馈篇幅过长的问题,本主尽量分开不同的知识点(PS:勤快点,别懒了),细致短促的讲解Go当中的知识点,以便朋友更加深入的学习。
- 分支、循环
- 函数
- 指针
- 结构体
1、分支、循环
(1) if 语句
语法格式如下:(与java类似,区别在于它的条件不需要括号"()")
if expression(表达式) {
/* 为 true 时执行 */
} else if expression2 {
/* 为 false ,expression2为true时执行 */
} else{
/* 都为false时,执行*/
}
示例:
func main() {
/* 定义局部变量 */
var a int = 2
/* 使用 if 语句判断布尔表达式 */
if a < 5 {
/* 如果条件为 true 则执行以下语句 */
fmt.Printf("a 小于 5\n" )
}
fmt.Printf("a 的值为 : %d\n", a)
}
(2)switch 语句
语法格式如下:(与java类似,区别在于Go中不需要像java一样在每一个case当中显式声明break,当找到匹配项时自动跳出)
switch var1 { // var1可以是任意类型
case val1: // 可以是同类型的任意值
...
case val2: // 且必须是相同的类型
...
default:
...
}
示例:
package main
import "fmt"
func main() {
/* 定义局部变量 */
var name string = "bboyHan"
var salary int = 30
//方式一:
switch age {
case 30000: name = "Tom"
case 25000: name = "Jerry"
case 22000,25000,30 : name = "bboyHan" //case 后可以由多个数值
default: name = "unknown"
}
//方式二:
switch {
case name == "Tom" :
fmt.Printf("good man!\n" )
case name == "Jerry", name == "bboyHan" :
fmt.Printf("lazy man\n" )
case name == "Kimi" :
fmt.Printf("good woman\n" )
case name == "Tomy":
fmt.Printf("a dog\n" )
default:
fmt.Printf("unknown\n" );
}
fmt.Printf("He(She) is a %s \n", name );
注意点:case定义的常量不可以重复,case后可以有多个常量值。另外,case中的表达式是可选的,可以省略。如果该表达式被省略,则被认为是switch true,并且每个case表达式都被计算为true,并执行相应的代码块。
func main() {
num := 75
switch {
case num >= 0 && num <= 50:
fmt.Println("num is greater than 0 and less than 50")
case num >= 51 && num <= 100:
fmt.Println("num is greater than 51 and less than 100")
case num >= 101:
fmt.Println("num is greater than 100")
}
}
(3)select 语句
select会随机执行一个可运行的case。如果没有case可运行,它将会阻塞,直到有case可运行。通常可以使用在通信之上,比如接收和发送消息,生产者与消费者的关系等等。如果有多个case都可以运行,Select会随机公平地选出一个执行。其他不会执行。记住!其它的是不会执行。
package main
import "fmt"
func main() {
var c1, c2, c3 chan int //定义通信通道
var i1, i2 int
select {
case i1 = <-c1:
fmt.Printf("接收消息:received ", i1, " from c1\n")
case c2 <- i2:
fmt.Printf("发送消息:sent ", i2, " to c2\n")
case i3, ok := <-c3:
if ok {
fmt.Printf("接收消息:received ", i3, " from c3\n")
} else {
fmt.Printf("c3 is closed - 消息关闭\n")
}
default:
fmt.Printf("no communication - 未连接 \n")
}
}
2、循环语句
Golang当中,for是唯一的循环语句,并不像java一样还有while、dowhile等语法,显得更加简单明了。
语法结构:
for init; condition; post {
//执行内容
}
// init : 初始化语句,只执行一次
// condition : 判断条件
// post : 迭代后执行的语句
// init、condition、post 三部分都可以省略,可以选择,如:
for condition { }
for { }
示例:
package main
import "fmt"
func main() {
nums := []int{1, 2, 3}
sum := 0
for _, num := range nums { // 埋雷, orz,想知道"_"时什么意思请往下看
sum += num
}
fmt.Println(sum)
for i, num := range nums {
if num == 2 {
fmt.Println(i)
}
}
kvs:= map[string]string{"a":"apple","b":"banana"}
for k,v := range kvs{
fmt.Printf("%s - %s\n",k,v)
}
for i,c := range "go"{
fmt.Println(i,c) // 打印字符ASCII值
}
}
其中还有break、continue跳出循环语句的使用,与其它语言类似
//continue
func main() {
for i := 1; i <= 10; i++ {
if i%2 == 0 {
continue //跳出本次循环
}
fmt.Printf("%d ", i)
}
}
//break
func main() {
for i := 1; i <= 10; i++ {
if i > 5 {
break //当大于5时,结束循环
}
fmt.Printf("%d ", i)
}
fmt.Printf("\nline after for loop")
}
func main() {
var a int
A:
for a < 5 {
if a == 3 {
a++
goto A //当执行到这时,返回到第3行继续执行代码
}
fmt.Printf("%d, --- \n", a)
a++
}
}
2、函数
我在《入门篇》提到过一个Go语言当中必不可少的函数,就是main函数,所谓函数,就是执行特定任务的代码块,在Go中,函数定义比较有趣的一点就是,它可以有多个返回值,十分方便
(1)语法格式:
func funcName(param1 type1, param2 type2) (output1 type1, output2 type2) {
//...
//函数具体实现内容
//返回多个值
return value1, value2
}
示例:(定义两个数交换的函数)
func swap(i int, i2 int) (int, int) {
return i2,i
}
//输入3、5,得出结果5,3
func main() {
a,b := swap(3,5)
fmt.Println(a,b)
}
扫雷:上文当中出现了Go当中一个有趣的标识符,就是空白标识符"_",它的作用是可以代替任何类型的任何值。同时,它的作用还可以被当作一个占位符表示,在后续的函数方法当中不使用其值的情况下,就可以使用"_"来代替。
就像在上面的例子当中求数组[1,2,3]的和时,不需要使用索引的值,就使用了空白标识符
(3)可变参数
另外,Go同样支持可变参数的传递
示例:(定义一个函数,遍历并输出)
func numFunc(arg ...int) {
for _, n := range arg {
fmt.Printf("The number is: %d\n", n)
}
}
(2) 函数可作为变量
在Go中,函数也是一种变量,我们可以通过type来定义它,在下文介绍的结构体中实例具体阐述。
type count int
func NewCount(i int) count {
return count(i)
}
func main() {
c := NewCount(10)
fmt.Println(c)
}
3、指针
在函数当中,我们也听说过值传递和引用传递,在Go中,引入了一个指针的概念。所谓指针,就是指变量在内存当中,是存放于一个地址上的,修改变量实际是修改变量地址处的内存。
传递指针,其实就是引用的传递,那就让我们来看看如何定义指针的吧
语法格式:
var a *int // 使用"*",定义指针类型
var b = &a // 使用"&",接收a的地址
示例:
func main() {
var i int
var ptr *int
var pptr **int
i = 10
ptr = &i //接收i的地址值
pptr = &ptr //接收ptr的地址值
fmt.Printf("%d\n", i)
fmt.Printf("%d\n", *ptr)
fmt.Printf("%d\n", **pptr)
}
4、结构体
(1)接口
接口,即一组方法签名,当类型为接口中定义的方法进行实现时,就可以称之为实现了一个接口。在java当中我们也有面向对象的概念,这与OOP的概念十分相似,接口指定了类型应该具有的方法,类型决定了如何实现这些方法。
语法结构:
// 定义接口
type interface_name interface {
method1 [return_type]
method2 [return_type]
method3 [return_type]
...
methodN [return_type]
}
// 定义结构体
type struct_name struct {
...
}
// 实现接口方法
func (struct_name_variable struct_name) method_name1() [return_type] {
// 方法实现
...
}
func (struct_name_variable struct_name) method_namen() [return_type] {
// 方法实现
...
}
示例:
package main
import "fmt"
type dosomething interface {
work() int
study() int
}
type Student struct {
name string
age int
}
func (stu Student) work() int {
fmt.Printf("name:%s,age:%d -- work\n", stu.name, stu.age)
return 3
}
func (stu Student) study() {
fmt.Printf("name:%s,age:%d -- study\n", stu.name, stu.age)
}
func main() {
s1 := new(Student)
s1.name = "zhang san"
s1.age = 23
s2 := new(Student)
s2.name = "Li si"
s2.age = 23
i := s1.work // 作为变量使用
a := i()
fmt.Println(a)
s2.study()
}
我们知道,在java当中,有一个类叫做Object,且认为所有的类都继承实现了Object类,作为java当中的顶级存在。在Go中,虽然没有继承这一概念,但同样的,也认为任意的类型都实现了空interface(我们这样定义:interface{}),也就是包含0个method的interface。
注意点:
1、接口对象不能调用实现对象的属性
2、interface可以被任意的对象实现
3、一个对象可以实现任意多个interface
4、interface的变量可以持有任意实现该interface类型的对象
----------------------------------------------------------------------
后续章节,敬请期待......
有任何建议或问题,欢迎加微信一起学习交流,欢迎从事IT,热爱IT,喜欢深挖源代码的行业大牛加入,一起探讨。
个人微信号:bboyHan