来源自Go学习之旅
包
每个 Go 程序都是由包构成的。
程序从 main 包开始运行。
示例代码通过导入路径 “fmt” 和 “math/rand” 来使用这两个包。
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println("My favorite number is", rand.Intn(200))
}
结果:My favorite number is +一个范围在[0,200]的随机数
像上面我们导入包的时候是使用import(xx,yy)的格式,我们也可以分别导入
import "fmt"
import "math/rand"
导出名格式——首字母必须大写
在 Go 中,如果一个名字以大写字母开头,那么它就是已导出的。例如,Pizza 就是个已导出名,Pi 也同样,它导出自 math 包。
pizza 和 pi 并未以大写字母开头,所以它们是未导出的。
在导入一个包时,你只能引用其中已导出的名字。任何“未导出”的名字在该包外均无法访问。
package gopackage
import "fmt"
const X = 5
var Y = 10
// Add int 加
func Add(x, y int) int {
return x + y
}
// Minus int 减
func Minus(x, y int) int {
return x - y
}
func mutiply(x,y int) int {
return x * y
}
上述代码定义了一个gopackage包,里面定义了3个方法,但是在使用的时候mutiply方法是无法使用的,因为首字母没有大写
函数
函数可以没有参数或接受多个参数。
在本例中,add 接受两个 int 类型的参数。
注意类型在变量名 之后。(而Java会把类型放在变量名前面)
package main
import "fmt"
func main() {
fmt.Println(add(42, 13))
}
func add(x int, y int) int {
return x - y
}
Java版本
public add (int x,int y) int{
return x-y;
}
public static void main(){
System.out.println(add(42,13));
}
Go允许在连续两个或多个函数的已命名形参类型相同时,除最后一个类型以外,其它都可以省略。
package main
import "fmt"
func add(x, y int) int {
return x + y
}
func main() {
fmt.Println(add(42, 13))
}
多值返回——函数可以返回任意数量的返回值
package main
import "fmt"
//这里返回了两个值,所以相应的函数也要声明一个返回列表
func swap(x, y string) (string, string) {
return y, x
}
func main() {
a, b := swap("hello", "world")
fmt.Println(a, b)
}
命名返回值
Go 的返回值可被命名,它们会被视作定义在函数顶部的变量。
返回值的名称应当具有一定的意义,它可以作为文档使用。
即是说我们无需像普通函数那样每次在末尾返回结果,而是在函数/方法的签名中就把返回值定义好
(直接返回语句应当仅用在下面这样的短函数中。在长的函数中它们会影响代码的可读性。)
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
func main() {
fmt.Println(split(17))
}
变量
var声明变量
var 语句用于声明一个变量列表,跟函数的参数列表一样,类型在最后。
var可以出现在包或者函数级别
package main
import "fmt"
//我们只需要在相同类型变量的末尾声明类型即可
var c, python, java bool
func main() {
var i int
fmt.Println(i, c, python, java)
}
短变量声明——‘’:="
在函数中,简洁赋值语句 := 可在类型明确的地方代替 var 声明。
函数外的每个语句都必须以关键字开始(var, func 等等),因此 := 结构不能在函数外使用。
变量的初始化
变量声明可以包含初始值,每个变量对应一个。
如果初始化值已存在,则可以省略类型;变量会从初始值中获得类型。
如果变量声明时没有初始值,那么会赋给每个变量相应类型的默认零值(int:0,bool:false,string:“”(空字符串))
package main
import "fmt"
func main() {
var i int
var f float64
var b bool
var s string
fmt.Printf("%v %v %v %q", i, f, b, s)
}
结果:0 0 false “”
package main
import "fmt"
//这里的int其实可以省略,i和j会自动从初始值获取参数类型
var i, j int = 1, 2
func main() {
var c, python, java = true, false, "no!"
fmt.Println(i, j, c, python, java)
}
Go的基本类型
string
int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr
byte // uint8 的别名
rune // int32 的别名
// 表示一个 Unicode 码点float32 float64
complex64 complex128
int, uint 和 uintptr 在 32 位系统上通常为 32 位宽,在 64 位系统上则为 64 位宽。 当你需要一个整数值时应使用 int 类型,除非你有特殊的理由使用固定大小或无符号的整数类型。
类型转换
表达式 T(v) 将值 v 转换为类型 T。
var i = 42
var f float64=float64(i)
var u uint = uint(f)
或者这种形式也可以
i := 42
f := float64(i)
u := uint(f)
Go在不同类型的项之间赋值的时候需要显式转换(意思是如果在类型转换的时候还需要进行其他操作,那么一定要显式转换)
类型推导
在声明一个变量而不指定其类型时(即使用不带类型的 := 语法或 var = 表达式语法),变量的类型由右值推导得出。
当右值声明了类型时,新变量的类型与其相同:
var i int
j := i // j 也是一个 int
不过当右边包含未指明类型的数值常量时,新变量的类型就可能是 int, float64 或 complex128 了,这取决于常量的精度:
常量
常量的声明与变量类似,只不过是使用 const 关键字。
常量可以是字符、字符串、布尔值或数值。
常量不能用 := 语法声明。
const World = "世界"
//World = "no"会报错,常量不可以修改
Go的type关键字
1.type定义结构体
type person struct{
name string
age int
// 在结构体定义中,每个变量后面无需加逗号
}
我们对上面定义好的结构体进行初始化
func main(){
p := person{
name:"zhl",
age:21,
}
// 在初始化一个结构体的时候,里面的变量要一一对应,并且每个变量后面要有逗号
fmt.Println(p.age)
}
但是在初始化结构体的时候无需对每个变量都赋值,如下:
p := person{
age:18,
// 这时候name的值就是string的零值——空字符串
}
2.type定义类型(int、string…)
我们可以使用type定义一个类型,如下所示
type name string
其实name就是string类型,只不过名称变成了name而已,我们接下来还可以使用name来定义字符串
type name string
func main(){
var myname name = "zhl" //其实myname就是string类型
l := []byte(myname) // 将字符串转换成字节数组
fmt.Println(len(l))
}
type定义类型并不仅仅是对类型进行重命名那么简单,我们也可以根据这个新的类型名定义方法
type name string
func (n name) length() int{
return len(n)
}
// 这个name类型的length方法其实底层也是调用的len方法
func main(){
var myname name = "zhl"
l := []byte(myname)
fmt.Println(len(l))
fmt.Println(myname.length()) //调用定义的新方法
}