7.1 Go语言参考手册
1. Hello World
package main
import "fmt"
func main() {
// 控制台单行输出
fmt.Println("Hello world!")
// 连续输出
fmt.Print("Hello ")
fmt.Print("world again!\n") // \n换行
// 中文
fmt.Print("你好")
}
2. 变量
package main
import "fmt"
func main() {
// using var
var name1 string = "Zlq"
fmt.Println(name1)
var age1 int = 43
fmt.Println(name1, age1)
fmt.Printf("age1 is %T\n", age1) // 屏幕输出变量类型 %T
fmt.Printf("say again age1 is %d hehe\n", age1)
// 常量定义
const isCool = true
//isCool = false
fmt.Println(isCool)
fmt.Printf("isCool is %T\n", isCool)
// 简短定义
name2 := "adida5"
fmt.Printf("%s is %T\n", name2, name2)
// 一行
name3, email := "zlq", "zhouleqing@126.com"
fmt.Println(name3, email)
}
3. 条件分支
package main
import "fmt"
func main() {
// using var
var name1 string = "Zlq"
fmt.Println(name1)
var age1 int = 43
fmt.Println(name1, age1)
fmt.Printf("age1 is %T\n", age1) // 屏幕输出变量类型 %T
fmt.Printf("say again age1 is %d hehe\n", age1)
// 常量定义
const isCool = true
//isCool = false
fmt.Println(isCool)
fmt.Printf("isCool is %T\n", isCool)
// 简短定义
name2 := "adida5"
fmt.Printf("%s is %T\n", name2, name2)
// 一行
name3, email := "zlq", "zhouleqing@126.com"
fmt.Println(name3, email)
}
4. 循环
package main
import "fmt"
func main() {
i := 1
for i < 10 {
fmt.Println(i)
i++
}
for j := 0; j < 10; j++ {
fmt.Println("Number", j)
}
for i := 1; i <= 100; i++ {
if i % 5 == 0 {
fmt.Printf("%d 是 5 的整数倍\n", i)
}
if i > 50 {
break
}
}
}
5. 函数
package main
import "fmt"
func greeting(name string) string {
return "Hello " + name
}
func main() {
fmt.Println(greeting("zlq"))
}
6. 包
目录结构:
├── main.go
└── mypackage
├── my_mult.go
└── my_package.go
my_mult.go:
package mypackage
func Mult(x, y int)int {
r := 0
for i := 0; i < y; i++ {
//r = r + x
r = plus(r, x)
}
return r
}
my_package.go:
package mypackage
// 大写字母开头的函数外部可以使用
func Myfunc_plus(x, y int) int {
return x + y
}
// 包外不可以用
func plus(x, y int) int {
return x + y
}
main.go
package main
import (
"fmt"
"math" // 用系统的包
"mygo_test/06_packages/mypackage" //用自己的包
)
func main() {
fmt.Println(math.Floor(1.7))
fmt.Println(math.Ceil(1.7))
fmt.Println(math.Sqrt(9))
fmt.Println(mypackage.Myfunc_plus(1, 3))
//fmt.Println(mypackage.plus(2, 4))
fmt.Println(mypackage.Mult(3, 5))
}
7. 数组
package main
import "fmt"
func main() {
// 定义 再 赋值
var fruitsArr [2]string
fruitsArr[0] = "apple"
fruitsArr[1] = "orange"
fmt.Println(fruitsArr)
fmt.Println(fruitsArr[1])
// 定义 并 赋值
phonesArr := []string{"iphone", "mi", "huawei", "oppo"}
fmt.Println(phonesArr)
// 数组长度
length := len(phonesArr)
fmt.Println("phonesArr 长度=", length)
// 遍历数组
fmt.Println("遍历方法1 for循环len(ary)")
for i := 0; i < length; i++ {
fmt.Println(i, phonesArr[i])
}
fmt.Println("遍历方法2 用range, 不想要下标索引的话 i 用_代替 (_, item := range arr)")
for i, item := range phonesArr {
fmt.Println(i, item)
}
// 增加元素
phonesArr = append(phonesArr, "vivo")
fmt.Println("增加元素vivo以后的数组:", phonesArr)
// 数组切片 左包右不包
pArr1 := phonesArr[:1] // 从开始 切到 0
pArr2 := phonesArr[1:3] // 从下标1开始 切到 2
pArr3 := phonesArr[2:] // 从下标2开始 切到最后
fmt.Println("[:1] 从开始切到下标是0的数组:", pArr1)
fmt.Println("[1:3] 从下标1开始切到2的数组:", pArr2)
fmt.Println("[2:] 从下标2开始 切到最后的数组:", pArr3)
// 删除数组中的元素
which := 2
phonesArr = append(phonesArr[:which], phonesArr[which+1:]...)
fmt.Println("删除下标是which以后的数组:", phonesArr)
}
8. Map
package main
import "fmt"
func main() {
// 定义map
emails := make(map[string]string)
// 分配键值对
emails["张三"] = "zhangshan@gmail.com"
emails["李四"] = "lisi@126.com"
fmt.Println(emails)
fmt.Println(len(emails))
fmt.Println(emails["张三"])
// 删除
delete(emails, "张三")
fmt.Println(emails)
// 定义并初始化map
emails2 := map[string]string{
"张三" : "zhangsan@gmail.com",
"王五" : "wangwu@126.com",
}
fmt.Println(emails2)
// 遍历map
for k, v := range emails2 {
fmt.Printf("key=%s, value=%s \n", k, v)
}
// 遍历 key
for k := range emails2 {
fmt.Printf("key=%s \n", k)
}
// 遍历 value
for _, v := range emails2 {
fmt.Printf("value=%s \n", v)
}
}
9. 指针
package main
import "fmt"
func main() {
a := 5
p := &a // p是指向a的指针
fmt.Println(a, p)
fmt.Printf("p 的类型是 %T \n", p)
fmt.Printf("p指向的值用*p取得: %d \n", *p)
*p = 100
fmt.Printf("修改*p的值为100以后, a的值: %d \n", a)
}
10. 闭包
package main
import "fmt"
func adder() func(int)int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
func main() {
sum := adder()
for i := 1; i <= 10; i++ {
fmt.Println(sum(i))
}
}
在 Go 语言中,闭包(Closure)是一个函数值,它来自于函数体的外部的变量引用。闭包函数可以对这些引用的变量进行访问和修改,即使在其定义之后这些变量已经脱离了作用域。换句话说,闭包允许将函数作为一个变量来使用,比如可以将一个函数作为参数传递给另外一个函数。
以下是一个简单的闭包函数的示例:
func plusX(x int) func(int) int {
return func(y int) int { return x + y }
}
func main() {
p := plusX(10)
fmt.Println(p(20)) // 输出 30
}
在这个例子中,函数 plusX
返回一个新的函数,这个新函数在执行时会将传入的参数与变量 x
(它是 plusX
的参数)相加。在 main
函数中,我们获取了这个新函数并把其赋值给了变量 p
,然后调用这个函数 p
,并传入了参数 20,得到了返回值 30。
在这个例子中,x
是在 plusX
函数的内部定义的变量,但是在 plusX
函数返回的匿名函数中仍然可以被访问和修改,这就是闭包的特性。
在Go语言中,闭包(Closure)指的是一个函数值(函数变量),它引用了外部函数作用域中的变量。简单来说,闭包可以让你在一个函数中访问另一个函数中的变量。
当你在一个函数内部定义了另一个函数,并且这个内部函数访问了外部函数的局部变量,那么内部函数就成为了闭包。在闭包中,外部函数的局部变量被保留在内存中,并且可以被内部函数继续访问和操作。
下面是一个 Go 语言中的闭包的例子:
func outer() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
counter := outer()
fmt.Println(counter())
fmt.Println(counter())
}
在这个例子中,outer()
返回一个匿名函数,匿名函数可以访问 outer()
中的局部变量 count
。每次调用这个匿名函数,count
的值都会增加并返回。在 main()
函数中,我们首先使用 outer()
返回的函数创建了一个新的变量 counter
,并调用两次,每次调用 counter()
,它都会返回一个新的自增的值。
通过闭包,我们可以实现很多更加复杂的功能,例如保持一些状态,缓存对象等。但是需要注意,过度使用闭包可能会导致内存泄漏,所以需要谨慎使用。
11. 结构体
package main
import (
"fmt"
"strconv"
)
// 定义结构体
type Student struct {
name string
gender string
age int
}
// 结构体的方法 value reciever
func (s Student)greet() string {
return "Hello, 我叫" + s.name + " 我今年" + strconv.Itoa(s.age) + "岁"
}
func (s Student)turnOldError() {
s.age++
}
// pointer reciever 想改变值需要传指针
func (s *Student)turnOld() {
s.age++
}
func main() {
stu1 := Student{name: "张三", gender: "男", age: 20}
fmt.Println(stu1)
stu1.age++
fmt.Println(stu1.age)
stu2 := Student{name: "李四", gender: "女", age: 19}
fmt.Println(stu2.greet())
stu2.turnOldError()
fmt.Println(stu2)
stu2.turnOld()
fmt.Println(stu2)
}
12. 接口
package main
import (
"fmt"
"math"
)
// 定义接口
type Shape interface {
area() float64
}
type Circle struct {
x, y, radius float64
}
type Rectangle struct {
width, height float64
}
func (c Circle)area() float64 {
return math.Pi * c.radius * c.radius
}
func (r Rectangle)area() float64 {
return r.width * r.height
}
func getArea(s Shape) float64 {
return s.area()
}
func main() {
circle := Circle{x: 0, y:0, radius: 10}
rectange := Rectangle{width: 5, height: 10}
fmt.Println(getArea(circle))
fmt.Println(getArea(rectange))
}
13. WEB
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", index)
fmt.Println("Web server starting...")
http.ListenAndServe(":8000", nil)
}
func index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "<h1>Hello web</h1>")
}
14. RESTful API
package main
import (
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"log"
"math/rand"
"net/http"
"strconv"
)
//book struct (Model)
type Book struct {
ID string `json:"id"`
ISBN string `json:"isbn"`
Title string `json:"title"`
Author *Author `json:"author"`
}
type Author struct {
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
}
// Init books var as slice Book struct
var books []Book
func getBooks(w http.ResponseWriter, r *http.Request) {
log.Println("Get all books")
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(books)
}
func getBook(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
params := mux.Vars(r)
log.Println("Get Book ", params["id"])
for _, item := range books {
if item.ID == params["id"] {
json.NewEncoder(w).Encode(item)
return
}
}
json.NewEncoder(w).Encode(&Book{})
}
func creatBook(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var book Book
_ = json.NewDecoder(r.Body).Decode(&book)
book.ID = strconv.Itoa(rand.Intn(1000000))
books = append(books, book)
json.NewEncoder(w).Encode(book)
}
func updateBook(w http.ResponseWriter, r *http.Request) {
fmt.Println("Update Book")
w.Header().Set("Content-Type", "application/json")
var book Book
_ = json.NewDecoder(r.Body).Decode(&book)
params := mux.Vars(r)
which := -1
for i, item := range books {
if item.ID == params["id"] {
which = i
break
}
}
if which >= 0 {
books[which] = book
}
json.NewEncoder(w).Encode(books)
}
func deleteBook(w http.ResponseWriter, r *http.Request) {
fmt.Println("Delete Book")
w.Header().Set("Content-Type", "application/json")
params := mux.Vars(r)
for i, item := range books {
if item.ID == params["id"] {
books = append(books[:i], books[i+1:]...)
break
}
}
json.NewEncoder(w).Encode(books)
}
func main() {
fmt.Println("Hello rest api")
r := mux.NewRouter()
//Mock data todo implement db
books = append(books, Book{
ID: "01",
ISBN: "1001",
Title: "Book One",
Author: &Author{
Firstname: "zhang",
Lastname: "san",
},
})
books = append(books, Book{
ID: "02",
ISBN: "2002",
Title: "Book Two",
Author: &Author{
Firstname: "li",
Lastname: "si",
},
})
// Route Handlers / Endpoints
r.HandleFunc("/api/books", getBooks).Methods("GET")
r.HandleFunc("/api/books/{id}", getBook).Methods("GET")
r.HandleFunc("/api/books", creatBook).Methods("POST")
r.HandleFunc("/api/books/{id}", updateBook).Methods("PUT")
r.HandleFunc("/api/books/{id}", deleteBook).Methods("DELETE")
log.Fatal(http.ListenAndServe(":8800", r))
}