作者:京东科技 韩国凯
前言
Go语言定义
Go(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态、强类型、编译型语言。Go 语言语法与 C 相近,但功能上有:内存安全,GC,结构形态及 CSP-style 并发计算
。
适用范围
本篇文章适用于学习过其他面向对象语言(Java、Php),但没有学过Go语言的初学者。文章主要从Go与Java功能上的对比来阐述Go语言的基础语法、面向对象编程、并发与错误四个方面。
一、基础语法
Go语言的基础语法与常规的编程语言基本类似,所不同的有声明变量的方式,数组、切片、字典的概念及功能与Java不太相同,不过Java中这些数据结构都可以通过类比功能的方式在Go中使用。
1.1 变量、常量、nil与零值、方法、包、可见性、指针
1.1.1 变量声明
Go语言中有两种方式
1.使用var
关键字声明,且需要注意的是,与大多数强类型语言不同,Go语言的声明变量类型位于变量名称的后面。Go语句结束不需要分号。
var num int
var result string = "this is result"
2.使用:=
赋值。
num := 3
等同于 var num int = 3
其中变量的类型会根据右侧的值进行匹配,例如"3"会匹配为int,"3.0"会匹配为float64,"result"会匹配为string。
1.1.2 常量声明
使用const
来声明一个常量,一个常量在声明后不可改变。
const laugh string = "go"
1.1.3 nil与零值
只声明未赋值的变量,其值为nil。类似于java中的“null” 。
没有明确初始值的变量声明会被赋予它们的 零值。
零值是:
- 数值类型为
0
, - 布尔类型为
false
, - 字符串为
""
(空字符串)。
1.1.4 方法、包
Go中方法的定义
使用func关键字来定义一个方法,后面跟方法名,然后是参数,返回值(如果有的话,没有返回值则不写)。
func MethodName(p1 Parm, p2 Parm) int{}
//学习一个语言应该从Hello World开始!
package main
import "fmt"
func main() {
fmt.Println("Hello World!")// Hello World!
fmt.Println(add(3, 5)) //8
var sum = add(3, 5)
}
func add(a int, b int) int{
return a+b;
}
多个返回值
Go 函数与其他编程语言一大不同之处在于支持多返回值,这在处理程序出错的时候非常有用。例如,如果上述 add
函数只支持非负整数相加,传入负数则会报错。
//返回值只定义了类型 没有定义返回参数
func add(a, b int) (int, error) {
if a < 0 || b < 0 {
err := errors.New("只支持非负整数相加")
return 0, err
}
a *= 2
b *= 3
return a + b, nil
}
//返回值还定义了参数 这样可以直接return 并且定义的参数可以直接使用 return时只会返回这两个参数
func add1(a, b int) (z int, err error) {
if a < 0 || b < 0 {
err := errors.New("只支持非负整数相加")
return //实际返回0 err 因为z只定义没有赋值 则nil值为0
}
a *= 2
b *= 3
z = a + b
return //返回 z err
}
func main() {
x, y := -1, 2
z, err := add(x, y)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Printf("add(%d, %d) = %d\n", x, y, z)
}
变长参数
func myfunc(numbers ...int) {
for _, number := range numbers {
fmt.Println(number)
}
}
slice := []int{1, 2, 3, 4, 5}
//使用...将slice打碎传入
myfunc(slice...)
包与可见性
在 Go 语言中,无论是变量、函数还是类属性和成员方法,它们的可见性都是以包为维度的,而不是类似传统面向编程那样,类属性和成员方法的可见性封装在所属的类中,然后通过 private
、protected
和 public
这些关键字来修饰其可见性。
Go 语言没有提供这些关键字,不管是变量、函数,还是自定义类的属性和成员方法,它们的可见性都是根据其首字母的大小写来决定的,如果变量名、属性名、函数名或方法名首字母大写,就可以在包外直接访问这些变量、属性、函数和方法,否则只能在包内访问,因此 Go 语言类属性和成员方法的可见性都是包一级的,而不是类一级的。
假如说一个名为domain
的文件夹下有3个.go文件,则三个文件中的package
都应为domain
,其中程序的入口main方法所在的文件,包为main
//定义了此文件属于 main 包
package main
//通过import导入标注库中包
import "fmt"
func main() {
fmt.Println("Hello World!")// Hello World!
fmt.Println(add(3, 5)) //8
var sum = add(3, 5)
}
func add(a int, b int) int{
return a+b;
}
1.1.5 指针
对于学过C语言来说,指针还是比较熟悉的,我所理解的指针,其实就是一个在内存中实际的16进制的地址值,引用变量的值通过此地址去内存中取出对应的真实值。
func main() {
i := 0
//使用&来传入地址
fmt.Println(&i) //0xc00000c054
var a, b int = 3 ,4
//传入 0xc00000a089 0xc00000a090
fmt.Println(add(&a, &b))
}
//使用*来声明一个指针类型的参数与使用指针
func add(a *int, b *int)int{
//接收到 0xc00000a089 0xc00000a090
//前往 0xc00000a089位置查找具体数据 并取赋给x
x := *a
//前往 0xc00000a090位置查找具体数据 并取赋给y
y := *b
return x+y
}
1.2 条件、循环、分支
1.2.1 条件
与Java语言的if基本相同
// if
if condition {
// do something
}
// if...else...
if condition {
// do something
} else {