Go 语言允许创建函数,在 Java 里叫方法。函数是多条语句的集合,用于组织代码结构,使代码更具易读性,通常用于实现一个特定的功能。
前些例子里,我们使用的都是 main
函数,也就是用于方法的入口。
这一节我们来学习下函数部分。
main 函数
main()
函数是程序执行的入口,在代码中只能有一个 main()
函数。 如果我们创建的是可执行程序,则需要有 main()
函数,如果创建的是 Go 包,则无需编写 main()
函数。
包的概念,我们现在还没学到,后边再看,大概猜测类似于 Java 里的包概念,也就是用于实现功能,但不负责执行。
在 Java 中 main 方法是这样的:
// java
public static void main(String[] args) {
}
但是 Go 中的 main 函数是这样的:
// go
func main() {
}
main()
函数相比于 Java 没有任何参数,并且也没有返回值。 但是,Go 的 main
方法也可以使用 os 包 和 os.Args
变量 来读取命令行参数。
// go
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
num1, _ := strconv.Atoi(os.Args[1])
num2, _ := strconv.Atoi(os.Args[2])
fmt.Println("Sum:", num1 + num2)
}
如何自定义函数
我们先来看下 Java 的自定义方法:
// java
访问范围 返回值类型 方法名称 (参数) {
方法体
}
public Integer sum(String num1, String num2) {
// 暂时不做校验
return Integer.valueOf(num1) + Integer.valueOf(num2);
}
// go
func 方法名称 (参数) (返回值) {
方法体
}
func sum(num1 string, num2 string) int {
return strconv.Atoi(num1) + strconv.Atoi(num2);
}
大概可以看出来两个方法的差异:
- 参数定义的方式
- 返回值的位置:Java 在前,Go 在后
Go 语言还有个地方就是可以在函数头中定义返回值变量,并且可以定义多个变量,是不是有点像 Python?
// go
func sum(num1 string, num2 string) (sum int, mul int) {
int1, _ := strconv.Atoi(num1)
int2, _ := strconv.Atoi(num2)
sum = int1 + int2
mul = int1 * int2
return
}
我个人觉得其实我们函数最好还是一个返回值,避免外部使用适合的混乱,当然多返回值的特性确实可以帮我们解决很多麻烦的代码段拆分的问题。
不过如果要使用,一定要:取容易理解的变量名,写好注释。
如何在函数内更改外部变量的值 -> 指针
Go 语言和 Java 一样,都是值传递的。也就是说我们上述的方法中,我们是没有办法改变 num1
num2
变量的值的;我们举个例子:
func rename(name string) {
name = "BEATREE";
}
func main() {
var name string = "Tom";
fmt.Println("name before rename:", name); // Tom
rename(name);
fmt.Println("name after rename:", name); // Tom
}
也就是说,在函数内部改变参数的值并不可行。其实这个和 Java 同理,因为传递的都是 值本身而不是变量自身 ,因此改变了也改变的只是值。
但是别慌,Go 里还是有指针的。 Go 中,有两个运算符可用于处理指针:
&
运算符:用于取变量的地址*
运算符:用于取地址下的值,我们可以对地址进行访问和更新。
func rename(name *string) {
name = "BEATREE";
}
func main() {
var name string = "Tom";
fmt.Println("name before rename:", name); // Tom
rename(&name);
fmt.Println("name after rename:", name); // BEATREE
}
指针 是一个存放变量的内存地址的变量。
向函数传递指针时,不是传递的值,而是传递内存地址。也就是这个变量自身了,那么当我们在方法内部改变这个变量的时候,外部的变量因为读的也是这个地址下的内容,所以也会同步被更改。
那如果我把上边两个参数类型不同的方法放一块,GO 支持吗?
func rename(name string) {
name = "BEATREE";
}
func rename(name *string) { // 会报错滴
*name = "BEATREE";
}