Go语法速览
字符串
package main
import (
"bytes"
"fmt"
)
func main() {
var buffer bytes.Buffer
for i := 0; i < 1000; i++ {
buffer.WriteString("a")
}
fmt.Println(buffer.String())
}
指针数组
package main
import (
"fmt"
)
const MAX int = 3
func main() {
//数组
a := []int{10, 100, 200}
//指针数组
var ptr [MAX]*int
for i := 0; i < MAX; i++ {
ptr[i] = &a[i] /* 整数地址赋值给指针数组 */
}
//*((&ptr)[0]) = 1
*ptr[0] = 1
for i := 0; i < MAX; i++ {
fmt.Printf("a[%d] = %d\n", i, a[i])
fmt.Printf("a[%d] = %d\n", i, *ptr[i])
}
}
package main
import "fmt"
func main() {
array := [5]*int{1: new(int), 3: new(int)}
array[0] = new(int)
*array[0] = 2
doubleNum(array)
fmt.Println(*array[0])
}
//函数间传递数组
func doubleNum(arr [5]*int) {
for k, v := range arr {
fmt.Println(k, v)
if v != nil {
fmt.Println(k, *v)
}
}
}
结构体
package main
import (
"fmt"
"strconv"
)
type Book struct {
id int
name string
//嵌入类型
user
desc string
}
type user struct {
id int
name string
email string
}
func main() {
//忽略的字段为 0 或 空, author={}
cBook := Book{name: "C语言"}
cBook.id = 1002
bookInfo(cBook)
//不能忽略字段
gBook := Book{1001, "go语言", user{id: 2001, name: "andy", email: "[email protected]"}, ""}
//new它只接受一个参数,这个参数是一个类型,分配好内存后,返回一个指向该类型内存地址的指针。
//同时请注意它同时把分配的内存置为零,也就是类型的零值。
u := new(user)
u.name = "jon"
u.email = "[email protected]"
gBook.changeBookAuthor(*u)
bookInfo(gBook)
//嵌入类型可以用外部类型直接访问,也可以通过内部类型进行访问
fmt.Println(gBook.email)
log(gBook)
}
func bookInfo(book Book) {
fmt.Printf("id=%d,name=%s,author=%s,des=%s\n", book.id, book.name, book.user, book.desc)
}
//定义bo的类型是指针*Book,才会改变它的值
//如果bo的类型是Book,不会改变它的值
func (bo *Book) changeBookAuthor(user user) {
bo.user = user
bo.desc = "change user"
}
//如果内部类型实现了某个接口,那么外部类型也被认为实现了这个接口
type logger interface {
printLog()
}
func (u user) printLog() {
fmt.Println(strconv.Itoa(u.id) + "--" + u.name)
}
func log(logger logger) {
logger.printLog()
}
切片
package main
import "fmt"
func main() {
//slice:=make([]int,5,10)
slice := []int{1, 2, 3, 4, 5}
//切片slice[i:j] 长度:j-i 容量:k-i
newSlice := slice[1:3]
sliceInfo(newSlice)
newSlice = append(newSlice, 101)
sliceInfo(newSlice) //[2,3,101]
sliceInfo(slice) //slice = [1,2,3,101,5]
//修改一个索引的值后,发现原切片的值也被修改了,说明它们共用一个底层数组。
modify(slice)
sliceInfo(slice) //[1,10,3,101,5]
}
func sliceInfo(s []int) {
fmt.Printf("slice 长度:%d,容量:%d\n", len(s), cap(s))
for k, v := range s {
fmt.Println(k, "--", v)
}
}
func modify(slice []int) {
fmt.Printf("%p\n", &slice)
slice[1] = 10
}
一般我们在创建新切片的时候,最好要让新切片的长度和容量一样,这样我们在追加操作的时候就会生成新的底层数组,和原有数组分离,就不会因为共用底层数组而引起奇怪问题,因为共用数组的时候修改内容,会影响多个切片。
package main
import "fmt"
func main() {
slice := make([]int, 4, 4)
slice[0] = 1
slice[1] = 2
newSlice := slice[1:3:3] //长度是2;容量是2
sliceInfo(newSlice) //[2,0]
newSlice = append(newSlice, 101)
sliceInfo(newSlice) //[2,0,101]
sliceInfo(slice) //[1,2,0,0]
}
func sliceInfo(s []int) {
for i := 0; i < len(s); i++ {
fmt.Print(s[i], " ")
}
}
Map
package main
import "fmt"
func main() {
world := make(map[string]string)
world["China"] = "中国"
world["America"] = "美国"
//使用一个返回值,这个默认的返回值就是Map的键
for country := range world {
fmt.Println(world[country])
}
score := map[string]int{"one": 78, "two": 99}
for k, v := range score {
fmt.Println(k, "--", v)
}
fmt.Println(exist(score, "three")) //-1
fmt.Println(exist(score, "one")) //78
delete(score, "one")
fmt.Println(exist(score, "one")) //-1
}
func exist(m map[string]int, sc string) int {
v, ok := m[sc]
if ok {
return v
} else {
return -1
}
}
方法与函数
函数是指不属于任何结构体、类型的方法,也就是说,函数是没有接收者的;而方法是有接收者的,我们说的方法要么是属于一个结构体的,要么属于一个新定义的类型的
/*
提供的常用库,有一些常用的方法,方便使用
*/
package lib
// 一个加法实现
// 返回a+b的值
func Add(a, b int) int {
return a + b
}
函数名首字母小写,表示只能在该包内可见;首字母大写可供其他包调用。
两种类型的接收者:值接收者和指针接收者
在调用方法的时候,传递的接收者本质上都是副本,只不过一个是这个值副本,一是指向这个值指针的副本。指针具有指向原有值的特性,所以修改了指针指向的值,也就修改了原有的值。我们可以简单的理解为值接收者使用的是值的副本来调用方法,而指针接收者使用实际的值来调用方法
package main
import (
"fmt"
"strings"
)
type User struct {
name string
pwd string
}
func (an *User) initPwd() (result bool, pwd string) {
if strings.HasPrefix(an.name, "us") {
an.pwd = "123456"
result = true
} else {
result = false
}
pwd = an.pwd
return
}
func (an User) login() bool {
if an.pwd == "123456" {
return true
} else {
return false
}
}
func main() {
user := User{name: "us_andy"}
result, pwd := user.initPwd()
if result {
fmt.Printf("success! pwd = %s", pwd)
} else {
panic("fail pwd")
}
//ok := (&user).login()
ok := user.login()
if ok {
fmt.Println("login success")
} else {
fmt.Println("login fail")
}
}
函数作为参数
package main
import (
"fmt"
)
func main() {
callback(2, 1, Add)
}
func Add(a, b int) {
fmt.Printf("The sum of %d and %d is: %d\n", a, b, a+b)
}
func callback(x int, y int, f func(int, int)) {
f(x, y)
}
类型转换
package main
import "fmt"
type Filter func(it Base) bool
func ApplyFilter(list []Base, filters ...Filter) []Base {
temp := make([]Base, 0, len(list))
for _, v := range list {
keep := true
for _, f := range filters {
if !f(v) {
keep = false
break
}
}
if keep {
temp = append(temp, v)
}
}
return temp
}
type Base interface {
driver() string
}
type Heart interface {
boot()
}
type Diagram struct {
id int
name string
}
func (d Diagram) driver() string {
return "diagram driver"
}
func (d Diagram) boot() {
s := d.driver()
fmt.Println("boot..." + s)
}
type Canvas struct {
id int
name string
shape string
}
func (c Canvas) driver() string {
return "canvas driver"
}
func main() {
var recorders = make([]Base, 3, 3)
diagram := Diagram{1, "diagram1"}
recorders[0] = diagram
canvas := Canvas{id: 1, name: "canvas1", shape: "circle"}
recorders[1] = canvas
recorders = append(recorders, Canvas{2, "canvas2", "rectangle"})
re := ApplyFilter(recorders, func(it Base) bool {
//判断是否实现某接口,类型转换
if sv, ok := it.(Heart); ok {
sv.boot()
}
//类型判断
switch it.(type) {
case Canvas:
ca := it.(Canvas)
//做转换之后才可以访问具体类型的属性
if ca.shape == "rectangle" {
return true
} else {
return false
}
case Diagram:
return false
}
return false
})
fmt.Println(re) //canvas
}