备注:方法1.2.3可以在函数体外,声明全局变量;4只能在函数体内,声明局部变量
声明多行变量
var (
cc int = 100
dd bool = true
)
fmt.Println(“cc=”,cc,“dd=”,dd)" title=“” data-bs-original-title=“复制” aria-label=“复制”>
var xx, yy int = 100, 200
var mm, nn = 100, “abc”
var (
cc int = 100
dd bool = true
)
fmt.Println(“cc=”,cc,“dd=”,dd)
常量 const
常量是不允许修改的
const a int = 100
const (
BEIJING = 1
SHANGHAI = 2
)
iota:配合const使用,每行累加,第一行默认0
const (
BEIJING = 10 * iota
SHANGHAI
SHENZHEN
)
const (
a, b = iota+1,iota+2
c, d
g, h = iota2,iota3
)
函数
基本函数形式
func test(a string, b int) int {
return 100
}
多返回值
func test(a string, b int) (int, int) {
return 666, 777
}
func test(a string, b int) (r1 int, r2 int) {
r1 = 1000
r2 = 2000
return
}
方法作为参数
//函数式编程
func PrintBookInfo(do func(string, string, float64) (bookInfo string, finalPrice float64),
bookName, author string, price float64) {
bookInfo, finalPrice := do(bookName, author, price)
fmt.Println("bookInfo:", bookInfo)
fmt.Println("finalPrice:", finalPrice)
}
func main() {
PrintBookInfo(ShowBookInfoAndPrice, “AAA”, “BBB”, 99.99)
}" title=“” data-bs-original-title=“复制” aria-label=“复制”>
func ShowBookInfoAndPrice(bookName, author string, price float64) (string, float64) {
return bookName + author, price
}
func PrintBookInfo(do func(string, string, float64) (bookInfo string, finalPrice float64),
bookName, author string, price float64) {
bookInfo, finalPrice := do(bookName, author, price)
fmt.Println(“bookInfo:”, bookInfo)
fmt.Println(“finalPrice:”, finalPrice)
}
func main() {
PrintBookInfo(ShowBookInfoAndPrice, “AAA”, “BBB”, 99.99)
}
匿名函数
func main() {
PrintBookInfo2(“AAA”, “BBB”, 99.99)
}" title=“” data-bs-original-title=“复制” aria-label=“复制”>
func PrintBookInfo2(bookName, author string, price float64) {
do := func(string, string, float64) (bookInfo string, finalPrice float64) {
return bookName + author, price
}
fmt.Println(do(bookName, author, price))
}
func main() {
PrintBookInfo2(“AAA”, “BBB”, 99.99)
}
可变参数
func PrintBookNames(bookList …string) {
r := “”
for _, item := range bookList {
r += item
}
fmt.Println®
}
func main() {
PrintBookNames(“AAA”, “BBB”, “CCC”)
}
条件判断
import (
"fmt"
"net/http"
)
func VisitUrl(url string) (int, error) {
res, err := http.Get(url)
defer res.Body.Close()
if err != nil {
fmt.Println("ERROR:", err)
return res.StatusCode, err
} else {
fmt.Println("OK:", res.StatusCode)
return res.StatusCode, err
}
}
func SwitchShow(url string) {
if code, err := VisitUrl(url); err != nil {
fmt.Println("Switch Error:", err)
} else {
switch code {
case 200:
fmt.Println("请求成功")
case 404:
fmt.Println("网址不存在")
default:
panic("未知错误")
}
}
}
func main() {
SwitchShow(“http://www.baidu.com”)
}
" title=“” data-bs-original-title=“复制” aria-label=“复制”>
package main
import (
“fmt”
“net/http”
)
func VisitUrl(url string) (int, error) {
res, err := http.Get(url)
defer res.Body.Close()
if err != nil {
fmt.Println(“ERROR:”, err)
return res.StatusCode, err
} else {
fmt.Println(“OK:”, res.StatusCode)
return res.StatusCode, err
}
}
func SwitchShow(url string) {
if code, err := VisitUrl(url); err != nil {
fmt.Println(“Switch Error:”, err)
} else {
switch code {
case 200:
fmt.Println(“请求成功”)
case 404:
fmt.Println(“网址不存在”)
default:
panic(“未知错误”)
}
}
}
func main() {
SwitchShow(“http://www.baidu.com”)
}
import与init
hello.go
package main
import (
“GoStudy/lib1”
“GoStudy/lib2”
)
func main() {
lib1.Lib1Test(); //在外部调用的函数名首字母必须大写
lib2.Lib2Test();
}
//输出结果
//lib1.init()…
//lib2.init()…
//Lib1Test()…
//Lib2Test()…
lib1/lib1.go
package lib1
import “fmt”
func Lib1Test() {
fmt.Println(“Lib1Test()…”)
}
func init() {
fmt.Println(“lib1.init()…”)
}
lib2/lib2.go
package lib2
import “fmt”
func Lib2Test() {
fmt.Println(“Lib2Test()…”)
}
func init() {
fmt.Println(“lib2.init()…”)
}
注意:
导入匿名包(不执行包内的函数,但执行init方法)
import _ “GoStudy/lib2”
导入包别名
import l2 “GoStudy/lib2”
func main() {
l2.Lib2Test();
}
导入当前包中(可直接调用函数)
import . “GoStudy/lib2”
func main() {
Lib2Test();
}
指针 *
注:GO语言的指针不允许运算。
package main
import “fmt”
func changeValue(p *int) {
*p = 10;
}
func main() {
var a = 1
changeValue(&a)
fmt.Println(“a =”,a)
}
defer
函数结束前执行的机制(先入后出,在return方法后执行)
package main
import “fmt”
func func1() {
fmt.Println(“func1()…”)
}
func func2() {
fmt.Println(“func2()…”)
}
func func3() {
fmt.Println(“func3()…”)
}
func returnAndDefer() int {
defer func1()
defer func2()
defer func3()
return returnFunc()
}
func returnFunc() int {
fmt.Println(“returnFunc()…”)
return 0
}
func main() {
returnAndDefer()
}
returnFunc()…
func3()…
func2()…
func1()…
数组与动态数组
固定长度的数组
package main
import “fmt”
func test(arr []int) {
arr[0] = 111
}
func main() {
var myArr []int
test(myArr)
for k, v := range myArr2 {
fmt.Println(“index=”,k,“value=”,v)
}
}
动态数组(切片 slice)
动态数组是引用传递,实际上传递的是数组的指针,指向同一块内存
不同长度的动态数组形参是一样的
package main
import “fmt”
func test(arr []int) {
arr[0] = 111
}
func main() {
myArr := []int{1,2,3,4}
test(myArr)
for k, v := range myArr {
fmt.Println(“index=”,k,“value=”,v)
}
}
index= 0 value= 111
index= 1 value= 2
index= 2 value= 3
index= 3 value= 4
注:_表示匿名变量
切片的声明方式
声明slice1是一个切片,并且初始化,默认值是1,2,3,长度len是3
slice1 := []int{1, 2, 3}
声明slice2是一个切片,但是并没有分配空间,需要make分配空间(初始化值是0)
var slice2 = []int
slice2 = make([]int, 3)
声明slice3是一个切片并通过make分配空间(初始化值是0)
var slice3 []int = make([]int, 3)
声明slice4是一个切片并通过make分配空间(初始化值是0),通过:=推导出slice4是切片(常用)
slice4 := make([]int, 3)
切片的追加
len:长度,表示左指针到右指针间的距离
cap:容量,表示左指针到底层数组末尾的距离
切片的扩容机制:append时,如果长度增加后超过容量,则将容量翻倍(5 -> 10 -> 20)
var numbers = make([]int, 3, 5)
fmt.Printf(“len=%d,cap=%d,slice=%v”,len(numbers),cap(numbers),numbers)
向numbers追加一个元素1
numbers = append(numbers, 1)
fmt.Printf(“len=%d,cap=%d,slice=%v”,len(numbers),cap(numbers),numbers)
向numbers追加一个元素2
numbers = append(numbers, 2)
fmt.Printf(“len=%d,cap=%d,slice=%v”,len(numbers),cap(numbers),numbers)
向容量已满的slice追加元素
numbers = append(numbers, 3)
fmt.Printf(“len=%d,cap=%d,slice=%v”,len(numbers),cap(numbers),numbers)
切片的截取
s := []int{1,2,3}
s1 := s[0:2]
s2 := make([]int, 3)
copy(s2, s)
s1[0] = 100
fmt.Println(s)
fmt.Println(s1)
fmt.Println(s2)
map
声明方式
方式一:
- 声明myMap1是一种map类型,key是string,value是string
- 在使用map前,需要先用make给map分配数据空间
var myMap1 map[string]string
myMap1 = make(map[string]string, 10)
myMap1[“a”] = “aaa”
myMap1[“b”] = “bbb”
方式二:
myMap2 := make(map[int]string)
myMap2[0] = “a”
myMap2[1] = “b”
fmt.Println(myMap2)
方式三
myMap3 := map[int]string {
0 : “a”,
1 : “b”,
}
fmt.Println(myMap3)
使用方式
map也是引用传递,做参数时传递的是指针地址
添加
myMap2 := make(map[int]string)
myMap2[0] = “a”
myMap2[1] = “b”
遍历
for k, v := range myMap2 {
fmt.Printf(“k=%d,v=%s\n”,k,v)
}
删除
delete(myMap2, 0)
修改
myMap2[0] = “c”
面向对象
结构体
定义
type Book struct {
title string
auth string
}
使用
book2 := Book{title:"aaa",auth:"bbb"}
fmt.Println(book2)//{aaa bbb}
book3 := Book{“aaa”,“bbb”}
fmt.Println(book3)//{aaa bbb}" title=“” data-bs-original-title=“复制” aria-label=“复制”>
var book1 Book
book1.title = “Golang”
book1.auth = “Tom”
fmt.Println(book1)
book2 := Book{title:“aaa”,auth:“bbb”}
fmt.Println(book2)
book3 := Book{“aaa”,“bbb”}
fmt.Println(book3)
类
封装:类名,属性名,方法名首字母大写表示对外可以访问
this是调用该方法的对象的一个副本(拷贝)
func (this *Book) setName(title string) {
this.title=title
}
func (this Book) setAuth(auth string) {
this.auth=auth
}
func main() {
book := Book{title:“aaa”,auth:“bbb”}
book.setName(“ccc”)
book.setAuth(“ddd”)
fmt.Println(book)
}
继承
package main
import “fmt”
type Human struct {
name string
sex string
}
type SuperMan struct {
Human
level int
}
func (this *Human) Eat() {
fmt.Println(“Human Eat…”)
}
func (this *Human) Walk() {
fmt.Println(“Human Walk…”)
}
func (this *SuperMan) Walk() {
fmt.Println(“SuperMan Walk…”)
}
func (this *SuperMan) Fly() {
fmt.Println(“SuperMan Fly…”)
}
func main() {
tom := Human{“aaa”,“bbb”}
tom.Eat()
tom.Walk()
var s SuperMan
s.name = “Sss”
s.sex = “man”
s.level= 88
s.Walk()
s.Fly()
}
多态
interface本质是父类的一个指针
基本要素:
- 有一个父类(接口)
- 有子类实现了父类的全部接口方法
- 父类类型的变量(指针)指向(引用)子类的具体数据变量
}" title=“” data-bs-original-title=“复制” aria-label=“复制”>
package main
import “fmt”
type AnimalIF interface {
Sleep()
GetColor() string
}
type Cat struct {
color string
}
func (this *Cat) Sleep() {
fmt.Println(“Cat Sleep…”)
}
func (this *Cat) GetColor() string {
return this.color
}
type Dog struct {
color string
}
func (this *Dog) Sleep() {
fmt.Println(“Dog Sleep…”)
}
func (this *Dog) GetColor() string {
return this.color
}
func showAnimal(animal AnimalIF) {
animal.Sleep()
fmt.Println(“color=”,animal.GetColor())
}
func main() {
var animal AnimalIF
animal = &Cat{“White”}
animal.Sleep()
fmt.Println(“color=”,animal.GetColor())
dog := Dog{<span class="hljs-string">"Yellow"</span>}
showAnimal(&dog)
<span class="hljs-comment">//Dog Sleep...</span>
<span class="hljs-comment">//color= Yellow</span>
}
万能数据类型 interface{} (空接口)
interface{} 类型断言机制:arg.(string)
type Book struct {
tile string
}
func test(arg interface{}){
fmt.Println(arg)
//断言
_, ok := arg.(string)
if !ok {
fmt.Println(“arg is not string”)
}else{
fmt.Println(“arg is string”)
}
}
func main() {
book := Book{“Golang”}
test(book)//{Golang}
test(123)//123
test(“hello”)//hello
}" title=“” data-bs-original-title=“复制” aria-label=“复制”>
package main
import “fmt”
type Book struct {
tile string
}
func test(arg interface{}){
fmt.Println(arg)
_, ok := arg.(string)
if !ok {
fmt.Println(“arg is not string”)
}else{
fmt.Println(“arg is string”)
}
}
func main() {
book := Book{“Golang”}
test(book)
test(123)
test(“hello”)
}
变量类型
变量pair对
type
- static type:int/string
- concrete type:interfece所指的具体数据类型(系统runtime看得见的类型)
- value
}
func (this *Book) ReadBook() {
fmt.Println(“Read a book.”)
}
func (this *Book) WriteBook() {
fmt.Println(“Write a book.”)
}
func main() {
b := &Book{}//b: pair<type:Book, value:Book{}地址>
var r Reader//r: pair<type: 空, value: 空>
r = b //r: pair<type:Book, value:Book{}地址>
r.ReadBook()
var w Writer
w = r.(Writer)//w: pair<type:Book, value:Book{}地址>
//断言有两步:得到动态类型 type,判断 type 是否实现了目标接口。
//这里断言成功是因为 type 是 Book,而 Book 实现了 Writer 接口
w.WriteBook()
}" title=“” data-bs-original-title=“复制” aria-label=“复制”>
package main
import “fmt”
type Reader interface {
ReadBook()
}
type Writer interface {
WriteBook()
}
type Book struct {
}
func (this *Book) ReadBook() {
fmt.Println(“Read a book.”)
}
func (this *Book) WriteBook() {
fmt.Println(“Write a book.”)
}
func main() {
b := &Book{}//b: pair<type:Book, value:Book{}地址>
var r Reader//r: pair<type: 空, value: 空>
r = b //r: pair<type:Book, value:Book{}地址>
r.ReadBook()
var w Writer
w = r.(Writer)//w: pair<type:Book, value:Book{}地址>
//断言有两步:得到动态类型 type,判断 type 是否实现了目标接口。
//这里断言成功是因为 type 是 Book,而 Book 实现了 Writer 接口
w.WriteBook()
}
反射 reflect
例1:
package main
import (
“fmt”
“reflect”
)
func reflectNum(arg interface{}){
fmt.Println(“type:”, reflect.TypeOf(arg))
fmt.Println(“value:”, reflect.ValueOf(arg))
}
func main() {
var num float64 = 1.34556
reflectNum(num)
}
例2:
package main
import (
“fmt”
“reflect”
)
type User struct {
Id int
Name string
Age int
}
func (this User) Call(){
fmt.Printf(“User: %v”, this)
}
func DoFieldAndMethod(input interface{}){
inputType := reflect.TypeOf(input)
inputValue := reflect.ValueOf(input)
for i := 0; i < inputType.NumField(); i++ {
field := inputType.Field(i)
value := inputValue.Field(i).Interface()
fmt.Printf(“%s:%v = %v\n”,field.Name, field.Type, value)
}
for i := 0; i < inputType.NumMethod(); i++ {
inputMethod := inputType.Method(i)
fmt.Printf(“%s:%v\n”,inputMethod.Name, inputMethod.Type)
}
}
func main() {
user := User{1, “Lilei”, 18}
DoFieldAndMethod(user)
}
结构体标签 Tag
package main
import (
“fmt”
“reflect”
)
type User struct {
Name string info:"name" doc:"姓名"
Age int info:"age" doc:"年龄"
}
func findTag(input interface{}){
inputType := reflect.TypeOf(input).Elem()
for i := 0; i < inputType.NumField(); i++ {
taginfo := inputType.Field(i).Tag.Get(“info”)
tagdoc := inputType.Field(i).Tag.Get(“doc”)
fmt.Printf(“info:%s doc:%s\n”,taginfo, tagdoc)
}
}
func main() {
var u User
findTag(&u)
}
结构体标签在json中的应用
package main
import (
“fmt”
“encoding/json”
)
type User struct {
Name string <span class="hljs-type">json</span>:"name"
Age int <span class="hljs-type">json</span>:"age"
Hobby []string <span class="hljs-type">json</span>:"hobby"
}
func main() {
user := User{“lilei”, 18, []string{“dance”,“football”}}
//json编码
jsonStr, err := json.Marshal(user)
if err != nil {
fmt.Println(“Json marshal error.”)
return
}
fmt.Printf(“json = %s”,jsonStr)//json = {“name”:“lilei”,“age”:18,“hobby”:[“dance”,“football”]}
//json解码
user1 := User{}
err = json.Unmarshal(jsonStr, &user1)
if err != nil {
fmt.Println(“Json unmarshal error.”)
return
}
fmt.Println(user1)//{lilei 18 [dance football]}
}