// helloworld.go
package nladuo
import (
"fmt"
)
func PrintHelloWorld() {
fmt.Println("Hello World")
}
然后把之前的helloworld程序改为下面的这个。
package main
import (
"nladuo"
)
func main() {
nladuo.PrintHelloWorld()
}
这样,我们自己的包,就测试成功了。
注意:
1、go语言如果让外部引入包的话,函数名称开头必须大写,如果开头小写的函数只能在当前包内部引用。
2、包引入后,必须使用,如果不使用的话会报错。
package main
import (
"nladuo"
"fmt" //不能引用没有使用的包
)
func main() {
nladuo.PrintHelloWorld()
}
3、“{”不能另起一行(大括号不能另起一行),以下写法会报错:
package main
import (
"nladuo"
)
func main()
{ //不能另起一行
nladuo.PrintHelloWorld()
}
常见命令
go run 命令:直接编译并运行go文件。
go build命令:编译go文件,比如说使用go build helloworld.go之后,就会生成一个helloworld.exe文件。
go install命令:编译go文件,然后会放到GOBIN目录下,如果GOBIN在PATH里面的话,可以在任何一个地方运行自己的程序。
go doc命令:go语言的文档。比如要查看fmt包的Println函数,你可以输入一下命令。
go doc fmt.Println
除此之外,你还可以使用godoc(中间没空格)工具在网页上显示文档。
godoc -http=:8000
在浏览器上输入:127.0.0.1:8000,就可以看到完全的文档了。
更多详细用法,可以直接输入go
查看go语言的其它命令,使用go help查看详细用法。
输入go查看全部命令:
输入go help run查看go run命令的帮助:
变量
package main
import (
"fmt"
)
var str1 string = "str1" //声明全局变量
//str2 string := "str2" 不能这么声明全局变量
var ( //声明多个全局变量
str2 string = "str2"
str3 string = "str3"
)
func main() {
var num1 int = 1 //声明局部变量
var num2 = 2 //如果声明时可以确定类型 ,可以不写变量类型
//var num3 不能确定类型, 必须加上类型
var num3 int
num3 = 3
num4 := 4 //简易声明局部变量
fmt.Println(str1, str2, str3, num1, num2, num3, num4)
}
注意:不能有未使用的变量,在别的语言中,有未使用的变量会有警告,在go语言中会导致编译不通过。
条件判断
go语言和类c语言的差不多,不过不需要加括号
package main
import (
"fmt"
)
func main() {
a := 1
b := 2
if a > b {
fmt.Println("a > b")
} else if a == b {
fmt.Println("a == b")
} else {
fmt.Println("a < b")
}
}
另外,go语言还可以在if语句中进行初始化:
package main
import (
"fmt"
)
func main() {
if a := 1; a == 1 { //先初始化a为1,再进行判断
fmt.Println("a == 1")
}
}
循环
普通的for循环:
package main
import (
"fmt"
)
func main() {
for i := 0; i < 10; i++ {
fmt.Print(i, " ")
}
fmt.Println()
}
go语言的“while”循环
package main
import (
"fmt"
)
func main() {
i := 0
for i < 10 { //也用for
fmt.Print(i, " ")
i++
}
fmt.Println()
}
死循环:
package main
import (
"fmt"
"time"
)
func main() {
i := 0
for { //每两秒打印一个数
fmt.Println(i)
i++
time.Sleep(2 * time.Second) //程序休眠2秒
}
}
函数
定义一个普通的函数:
package main
import (
"fmt"
)
func myprint(v interface{}) { //go语言中interface{}可以代表任何类型,可以当成java中的Object类型
fmt.Println(v)
}
func main() {
myprint(100)
myprint("Hello World")
}
带多返回值的函数:
package main
import (
"fmt"
)
func swap(a int, b int) (int, int) {
return b, a
}
func main() {
a := 1
b := 2
fmt.Println("a =", a, "b =", b)
a, b = swap(a, b)
fmt.Println("a =", a, "b =", b)
}
方法
package main
import (
"fmt"
)
type MyInt int
func (this MyInt) getVal() int {
return int(this)
}
func main() {
var myInt MyInt = MyInt(1)
fmt.Println(myInt.getVal())
}
定义一个结构体,并添加String方法。
package main
import (
"fmt"
"strconv"
)
type Person struct {
Name string
Age int64
}
func (this Person) String() string { //类似java的toString方法
ageStr := strconv.FormatInt(this.Age, 10)
return "名字:" + this.Name + " 年龄:" + ageStr
}
func main() {
p := Person{Name: "nladuo", Age: 20}
fmt.Println(p) //不需要写fmt.Println(p.String())
}
有关指针的使用:
package main
import (
"fmt"
"strconv"
)
type Person struct {
Name string
Age int64
}
func (this Person) String() string { //类似java的toString方法
ageStr := strconv.FormatInt(this.Age, 10) //把int转换为string类型,第二个参数代表按照10进制转换
return "名字:" + this.Name + " 年龄:" + ageStr
}
func (this Person) ChangeName1(name string) {
this.Name = name
}
func (this *Person) ChangeName2(name string) {
this.Name = name
}
func main() {
p := Person{Name: "nladuo", Age: 20}
fmt.Println(p)
p.ChangeName1("Kalen Blue")
fmt.Println(p) //没有改变name
p.ChangeName2("Kalen Blue")
fmt.Println(p) //name 发生改变
}
通过指针的这个例子,可以知道,如果需要改变struct内部的值,就需要使用指针,而不使用指针的话,则相当于完全拷贝了一份,相比指针,一是不能改变变量的值,二是浪费储存空间。
一些类型
介绍go语言的数组、切片以及Map
数组
数组的创建和遍历
package main
import (
"fmt"
)
func main() {
arr := [5]int{1, 2, 3, 4, 5}
//遍历数组方式1
for i := 0; i < len(arr); i++ {
fmt.Print(i, " ")
}
fmt.Println()
//遍历数组方式2
for v := range arr {
fmt.Print(v, " ")
}
fmt.Println()
//遍历数组方式2,并获取索引
for k, v := range arr {
fmt.Println("index:", k, " value:", v)
}
fmt.Println()
}
go语言的数组和c语言的数组差不多,一旦声明,就无法改变长度了。所以我们更多用的是切片。
切片
数组和切片声明上的不同。
arr := [5]int{1, 2, 3, 4, 5}
slice := []int{1, 2, 3, 4, 5}
另一种声明方式,通过make来实现。make的第二个参数和第三个是声明slice的长度和容量。
其实是因为切片就是数组的一个引用,内部其实也指向一个数组,比如说下面的这个,内部指向一个长为5的底层数组,这个切片本身并没有元素。等到数组的容量不够的时候,go语言内部会帮助我我们修改底层数组的大小。
package main
import (
"fmt"
)
func main() {
slice := make([]int, 0, 5) //0是slice的长度,5代表slice的容量
fmt.Println("len:", len(slice))
fmt.Println("cap:", cap(slice))
}
切片的一些操作。
package main
import (
"fmt"
)
func printSlice(tag string, slice []int) {
fmt.Print(tag, " ")
for _, v := range slice {//一个下划线代表不关心索引的取值
fmt.Print(v, " ")
}
fmt.Println()
}
func main() {
var slice []int
fmt.Println("len:", len(slice))
fmt.Println("cap:", cap(slice))
for i := 0; i < 10; i++ {
slice = append(slice, i) //添加元素
}
printSlice("添加元素:", slice)
fmt.Println("len:", len(slice))
fmt.Println("cap:", cap(slice))
//添加切片,通用方式:slice1=append(slice1, slice2...)
slice = append(slice, []int{10, 11, 12, 13, 14, 15}...)
printSlice("添加切片:", slice)
fmt.Println("len:", len(slice))
fmt.Println("cap:", cap(slice))
printSlice("添加切片:", slice)
printSlice("slice[:3]:", slice[:3]) //slice[0]到slice[3]
printSlice("slice[4:]:", slice[4:]) //slice[4+1]到末尾
printSlice("slice[3:10]:", slice[3:10]) //slice[3+1]到slice[10]
printSlice("slice[:]:", slice[:]) //整个slice
//删除第3个元素
//通用方式,slice=append(slice[:i], slice[i+1:]...)
slice = append(slice[:3], slice[4:]...)
printSlice("删除第3个元素:", slice)
}
Map
map其实就是相当于哈希表或者叫字典,直接看看它的用法
package main
import (
"fmt"
)
func printMap(m map[string]string) {
for k, v := range m {
fmt.Println("key:", k, " value:", v)
}
fmt.Println()
}
func main() {
var lans map[string]string
lans = make(map[string]string) //必须使用make来初始化
//也可以直接使用 lans := make(map[string]string)
lans["go"] = "谷歌公司" //添加元素
lans["swift"] = "苹果公司"
lans["java"] = "Oracle公司"
printMap(lans)
//判断key是否存在
if v, ok := lans["java"]; ok {
fmt.Println("存在key:java 属于", v, "n")
} else {
fmt.Println("不存在key:java", "n")
}
delete(lans, "java") //删除元素
printMap(lans)
//判断key是否存在
if v, ok := lans["java"]; ok {
fmt.Println("存在key:java 属于", v, "n")
} else {
fmt.Println("不存在key:java", "n")
}
}