Java 太卷了转 GO(一)
GO 的一些基础用法,帮助 Java 程序员快速转 GO。
变量的声明
- 第一种,指定变量类型,声明后若不赋值,使用默认值0。
var a int
var a int = 10
- 根据值自行判定变量类型。
var a = 10
- 第三种,省略var, 注意 :=左侧的变量不应该是已经声明过的,否则会导致编译错误。
a := 10
常量
const b int = 10
const b = 10
枚举
常量可以用作枚举
const (
Unknown = 0
Female = 1
Male = 2
)
iota
它简化了常量用于增长数字的定义
const (
CategoryBooks = iota // 0
CategoryHealth // 1
CategoryClothing // 2
)
函数
package main
import "fmt"
func main() {
var a int = 10
var b int = 20
fmt.Println("1--", a, b)
swap(a, b)
fmt.Println("2--", a, b)
}
func swap(a int, b int) {
var c int = a
a = b
b = c
}
main 函数
main 函数只能出现在 package main 中。是程序的入口。
init 函数
init 函数可在package main中,可在其他package中,可在同一个package中出现多次。
执行顺序
golang里面有两个保留的函数:init函数(能够应用于所有的package)和main函数(只能应用于package main)。这两个函数在定义时不能有任何的参数和返回值。
go程序会自动调用init()和main(),所以你不需要在任何地方调用这两个函数。每个package中的init函数都是可选的,但package main就必须包含一个main函数。
如果main包还导入了其它的包,那么就会在编译时将它们依次导入。有时一个包会被多个包同时导入,那么它只会被导入一次(例如很多包可能都会用到fmt包,但它只会被导入一次,因为没有必要导入多次)。
当一个包被导入时,如果该包还导入了其它的包,那么会先将其它包导入进来,然后再对这些包中的包级常量和变量进行初始化,接着执行init函数(如果有的话),依次类推。

值传递
值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数。
swap 函数就是值传递的,交换两个数的操作,但是不会生效。
引用传递(指针传递)
&: 取地址
*: 解引用
package main
import "fmt"
func main() {
var a int = 10
var b int = 20
fmt.Println("1--", a, b)
swap2(&a, &b)
fmt.Println("2--", a, b)
}
func swap2(a *int, b *int) {
var c = *a
*a = *b
*b = c
}
defer
defer 相当于 java 中 finally
数组
var variable_name [SIZE] variable_type
var nums [10]int;
如果数组长度不确定,可以使用 ... 代替数组的长度
balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
切片
var identifier []type
未指定大小的数组来定义切片,切片不需要说明长度。
var slice1 []type = make([]type, len)
// 也可以简写为
slice1 := make([]type, len)
// 直接初始化
s :=[] int {1,2,3 }
// 直接初始化切片,[]表示是切片类型,{1,2,3}初始化值依次是1,2,3.其cap=len=3
len()长度,
cap()容量,当长度等于容量时扩容为当前长度的2倍。
append 和 copy 函数
append 用于向切片中追加一个元素,
package main
import "fmt"
func main() {
var numbers []int
printSlice(numbers)
/* 允许追加空切片 */
numbers = append(numbers, 0)
printSlice(numbers)
/* 向切片添加一个元素 */
numbers = append(numbers, 1)
printSlice(numbers)
/* 同时添加多个元素 */
numbers = append(numbers, 2,3,4)
printSlice(numbers)
/* 创建切片 numbers1 是之前切片的两倍容量*/
numbers1 := make([]int, len(numbers), (cap(numbers))*2)
/* 拷贝 numbers 的内容到 numbers1 */
copy(numbers1,numbers)
printSlice(numbers1)
}
func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}
map
Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type
/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)
结构体
package main
import "fmt"
// 类名大写,其他包也可以引用到。小写就不行
type Books struct {
title string
author string
}
// 普通函数,参数是结构体
func printBook(book Books) {
fmt.Printf("book = %v\n", book)
}
// 普通函数,参数是结构体,值传递,修改不会在 main 函数中生效
func SetTitle(book Books) {
book.title = "Python"
}
// 使用指针传递参数可以修改其属性值
func SetTitle2(book *Books) {
book.title = "Python"
}
// 这个函数相当于结构体的函数,可以 book.SetAuthor() 调用。
// 注意是个指针传递,可以写成值传递,但修改没有效果
func (t *Books) SetAuthor() {
t.author = "lisi"
}
func main() {
book := Books{"GO", "test"}
fmt.Println(book)
book.title = "C"
fmt.Println(book)
java := Books{title: "Java", author: "22"}
printBook(java)
SetTitle(java)
printBook(java)
SetTitle2(&java)
java.SetAuthor()
printBook(java)
}
继承
method
method 附属在一个给定类型上,语法和函数的语法几乎一样,只是在 func 后面增加了一个 receiver(也就是 method 所依从的主体)
method 给用户定义的类型添加新的行为。
method 的接收者可以是普通类型,也可以是指针类型,是普通类型的时候接收的值的副本,也就是值传递,是指针类型的时候接收的是内存地址,就是引用传递。
func (r receiverType) funcName(parameters) (results)
虽然 method 的名字一模一样,但是如果接收者不一样,那么 method 就不一样
method 继承
如果匿名字段实现了一个 method,那么包含这个匿名字段的 struct 也能调用该 method
package main
import (
"fmt"
)
type Human struct {
name string
sex string
}
func (t *Human) Eat() {
fmt.Println("eat")
}
func (t *Human) Walk() {
fmt.Println("walk")
}
type SuperHuman struct {
// 匿名字段,使得 SuperHuman 的对象也拥有 Human 的 method
Human
level int
}
// 重写 SuperHuman 的 Walk 方法。
func (t *SuperHuman) Walk() {
fmt.Println("fly")
}
func main() {
man := Human{
name: "zhangsan",
sex: "男",
}
man.Eat()
man.Walk()
// 创建子类对象
//superMan := SuperHuman{
// Human{"lisi", "男"}, 100,
//}
var superMan SuperHuman
superMan.level = 100
superMan.name = "lisi"
superMan.sex = "男"
superMan.Eat()
superMan.Walk()
}
interface
interface 本质上是个指针。
interface 定义了一组 method,如果某个对象实现了某个接口的所有方法,则此对象就实现了这个接口
interface 是一组抽象方法的集合,必须由其他非 interface 类型实现,而不能自我实现,
package main
import "fmt"
// 定义一个 interface,有两个方法 eat、run
type Anaimal interface {
eat()
run()
}
// ======
// 定义子类,实现 interface 中的 2个方法,必须要完全实现 interface 中的所有方法,才算是继承
type Dog struct {
}
func (dog Dog) eat() {
fmt.Println("dog eat")
}
func (dog Dog) run() {
fmt.Println("dog run")
}
// ======
type Cat struct {
}
func (cat Cat) eat() {
fmt.Println("cat eat")
}
func (cat Cat) run() {
fmt.Println("cat run")
}
// ======
func main() {
var anaimal Anaimal
anaimal = new(Dog)
anaimal.eat()
anaimal.run()
anaimal = new(Cat)
anaimal.eat()
anaimal.run()
}
以上这些就是 GO 的一些基础知识。学会了这些下面就能简单进行开发了。
下一篇文章介绍下 GO 的框架,ORM 框架,Web 框架,以及用这些开发一个小应用。
参考网站
https://learnku.com/go/wikis
https://learnku.com/docs/the-little-go-book
https://learnku.com/docs/the-way-to-go
https://www.yuque.com/aceld/mo95lb/dsk886
https://www.runoob.com/go/go-map.html
Copyright © 2015 Powered by MWeb, Theme used GitHub CSS.
