Skip to main content
Version: go

基础

package main
import "fmt"

type struct1 struct {
i1 int
f1 float32
str string
}

func main() {
ms := new(struct1)
ms.i1 = 10
ms.f1 = 15.5
ms.str= "Chris"

fmt.Printf("The int is: %d\n", ms.i1)
fmt.Printf("The float is: %f\n", ms.f1)
fmt.Printf("The string is: %s\n", ms.str)
fmt.Println(ms)
}

创建

可选的标签(tag):它是一个附属于字段的字符串,可以是文档或其他的重要标记。标签的内容不可以在一般的编程中使用,只有包 reflect 能获取它。

type Interval struct {
start int
end int
}

//带标签的结构体
type TagType struct { // tags
field1 bool "An important answer"
field2 string "The name of the thing"
field3 int "How much there are"
}


type Point struct { x, y int }

声明

var v myStruct    // v是结构体类型变量
var p *myStruct // p是指向一个结构体类型变量的指针
v.i
p.i

赋值

ms := &struct1{10, 15.5, "Chris"}
// 此时ms的类型是 *struct1 指针不是必须的

var ms struct1
ms = struct1{10, 15.5, "Chris"}


intr := Interval{0, 3} (A)
intr := Interval{end:5, start:1} (B)
intr := Interval{end:5} (C)

// 方法
func upPerson(p *Person) {
p.firstName = strings.ToUpper(p.firstName)
p.lastName = strings.ToUpper(p.lastName)
}

// 方法调用
upPerson(&pers1)

转换

package main
import "fmt"

type number struct {
f float32
}

type nr number // alias type

func main() {
a := number{5.0}
b := nr{5.0}
// var i float32 = b // compile-error: cannot use b (type nr) as type float32 in assignment
// var i = float32(b) // compile-error: cannot convert b (type nr) to type float32
// var c number = b // compile-error: cannot use b (type nr) as type number in assignment
// needs a conversion:
var c = number(b)
fmt.Println(a, b, c)
}

构造方法

// 创建
type File struct {
fd int // 文件描述符
name string // 文件名
}

// 构造方法
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}

return &File{fd, name}
}

// 调用
f := NewFile(10, "./test.txt")

方法

一个类型加上它的方法等价于面向对象中的一个类。

可以不同文件,但必须是同一个包

类型

func (a *denseMatrix) Add(b Matrix) Matrix
func (a *sparseMatrix) Add(b Matrix) Matrix

定义方法:

// 格式
func (recv receiver_type) methodName(parameter_list) (return_value_list) { ... }

this

recv 就像是面向对象语言中的 this 或 self

demo

package main

import (
"fmt"
)

// 类, 类字段
type B struct {
thing int
}

// 类方法
// 接受一个指向 B 的指针,并改变它内部的成员
func (b *B) change() { b.thing = 1 }

// 拷贝接受 B 的值并只输出 B 的内容
func (b B) write() string { return fmt.Sprint(b) }

func main() {
// 类初始化
var b1 B // b1是值
b1.change()
fmt.Println(b1.write())

b2 := new(B) // b2是指针
// b4 := B{1}
// b3 := &B{1} // b3 定义为一个指针
// b3.write() 来替代 (*b3).write()
b2.change
// 方法调用
fmt.Println(b2.write())
}

/* 输出:
{1}
{1}
*/

公有私有

  • public : 一个大写字母开头,如:Group1
    • 当标识符(包括常量、变量、类型、函数名、结构字段等等
  • private 如: name
    • 标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的

matrix.go

type matrix struct {
...
}

func NewMatrix(params) *matrix {
m := new(matrix) // 初始化 m
return m
}

// 对外提供访问私有字段

type Person struct {
firstName string
lastName string
}

func (p *Person) SetFirstName(newName string) {
p.firstName = newName
}

other.go

package main
import "matrix"
...
wrong := new(matrix.matrix) // 编译失败(matrix 是私有的)
right := matrix.NewMatrix(...) // 实例化 matrix 的唯一方式

p := new(matrix.Person)
p.SetFirstName("Eric")

继承

结构体

package main

import "fmt"

type innerS struct {
in1 int
in2 int
}

type outerS struct {
b int
c float32
int // anonymous field
innerS //anonymous field
}

func main() {
outer := new(outerS)
outer.b = 6
outer.c = 7.5
outer.int = 60
outer.in1 = 5
outer.in2 = 10

fmt.Printf("outer.b is: %d\n", outer.b)
fmt.Printf("outer.c is: %f\n", outer.c)
fmt.Printf("outer.int is: %d\n", outer.int)
fmt.Printf("outer.in1 is: %d\n", outer.in1)
fmt.Printf("outer.in2 is: %d\n", outer.in2)

// 使用结构体字面量
outer2 := outerS{6, 7.5, 60, innerS{5, 10}}
fmt.Println("outer2 is:", outer2)
fmt.Println(outer2.innerS)
}

继承覆盖

外层名字会覆盖内层名字

type A struct {a int}
type B struct {a, b int}

type C struct {A; B}
var c C

继承父类方法

package main

import (
"fmt"
"math"
)

// 父类和方法
type Point struct {
x, y float64
}

func (p *Point) Abs() float64 {
return math.Sqrt(p.x*p.x + p.y*p.y)
}

// 子类
type NamedPoint struct {
Point
name string
}

// 子类覆盖父类方法
func (n *NamedPoint) Abs() float64 {
return n.Point.Abs() * 100.
}

func main() {
// 父类初始化
n := &NamedPoint{Point{3, 4}, "Pythagoras"}
fmt.Println(n.Abs()) // 打印5
}

多重继承

package main

import (
"fmt"
)

type Camera struct{}

func (c *Camera) TakeAPicture() string {
return "Click"
}

type Phone struct{}

func (p *Phone) Call() string {
return "Ring Ring"
}

type CameraPhone struct {
Camera
Phone
}

func main() {
cp := new(CameraPhone)
fmt.Println("Our new CameraPhone exhibits multiple behaviors...")
fmt.Println("It exhibits behavior of a Camera: ", cp.TakeAPicture())
fmt.Println("It works like a Phone too: ", cp.Call())
}

结果

Our new CameraPhone exhibits multiple behaviors...
It exhibits behavior of a Camera: Click
It works like a Phone too: Ring Ring

接口

定义

//接口的名字由方法名加 [e]r
type Namer interface {
// 包含 0 个、最多 3 个方法
Method1(param_list) return_type
Method2(param_list) return_type
...
}

例子

// 1, 定义接口
type Engine interface {
Start()
Stop()
}

type Shaper interface {
Area() float32
}

// 2-1, 定义类型(类), 可以在这里实现接口, 也可以在初始化后使用接口
type Car struct {
Engine
}

type Square struct {
side float32
}

// 3, 实现接口方法
func (c *Car) GoToWorkIn() {
// get in car
c.Start()
// drive to work
c.Stop()
// get out of car
}

func (sq *Square) Area() float32 {
return sq.side * sq.side
}

func main(){
sql := new(Car)

// 2-2 一个类型可以有多个接口
var engineIntf Engine // engineIntf 它的值是 nil, 它本质上是一个指针
engineIntf = sql // sql 实现了接口, 可以赋值给 engineIntf
// shorter,without separate declaration:
engineIntf := Engine(sql) // 接口名称 单个
engineIntf := sql

// 检测接口类型
if t, ok := engineIntf.(*Car); ok {
fmt.Printf("The type of engineIntf is: %T\n", t)
}

// Car 是否实现了 Engine 接口
if sv, ok := sql.(Engine); ok {
fmt.Printf("v implements String(): %s\n", sv.String()) // note: sv, not v
}

}

接口嵌套

type ReadWrite interface {
Read(b Buffer) bool
Write(b Buffer) bool
}

type Lock interface {
Lock()
Unlock()
}

type File interface {
ReadWrite
Lock
Close()
}

多态

同一种类型在不同的实例上似乎表现出不同的行为。

package main

import "fmt"

// 形状
type Shaper interface {
Area() float32
}

// 平方
type Square struct {
side float32
}

func (sq *Square) Area() float32 {
return sq.side * sq.side
}

// 面积
type Rectangle struct {
length, width float32
}

func (r Rectangle) Area() float32 {
return r.length * r.width
}

func main() {

r := Rectangle{5, 3} // Area() of Rectangle needs a value
q := &Square{5} // Area() of Square needs a pointer

// 实现接口
// shapes := []Shaper{Shaper(r), Shaper(q)}
// or shorter
shapes := []Shaper{r, q} // 多个接口
fmt.Println("Looping through shapes for area ...")
for n, _ := range shapes {
fmt.Println("Shape details: ", shapes[n])
fmt.Println("Area of this shape is: ", shapes[n].Area())
}
}

结果

Looping through shapes for area ...
Shape details: {5 3}
Area of this shape is: 15
Shape details: &{5}
Area of this shape is: 25

方法集

/* 

指针: = 指针, = 值

值: <>指针, = 值
*/

package main

import (
"fmt"
)

type List []int

// 值
func (l List) Len() int {
return len(l)
}

// 指针
func (l *List) Append(val int) {
*l = append(*l, val)
}

type Appender interface {
Append(int)
}

// 指针
func CountInto(a Appender, start, end int) {
for i := start; i <= end; i++ {
a.Append(i)
}
}

type Lener interface {
Len() int
}

// 值
func LongEnough(l Lener) bool {
return l.Len()*10 > 42
}

func main() {
// A bare value 值
var lst List
// compiler error:
// cannot use lst (type List) as type Appender in argument to CountInto:
// List does not implement Appender (Append method has pointer receiver)
// CountInto(lst, 1, 10) // 值不可以调用指针
if LongEnough(lst) { // VALID:Identical receiver type
fmt.Printf("- lst is long enough\n")
}

// A pointer value 指针
plst := new(List)
CountInto(plst, 1, 10) //VALID:Identical receiver type
if LongEnough(plst) { // 指针可以调用值
// VALID: a *List can be dereferenced for the receiver
fmt.Printf("- plst is long enough\n")
}
}

Object

空接口

type Any interface {}