更新,好吧最开始照着官方文档写的demo 连入门都入不了,里面还有很多东西是需要花功夫研究的
go 的结构体 不用多说,和c/c++ 类似
可以定义然后直接使用,注意给的实参 用 , 分隔
func main(){
fmt.Println("zhangsan ", person{"zhangsan", 22})
fmt.Println(newPerson("zhangsan", 22))
s := person{name: "lisi", age: 24}
fmt.Println(s.name)
fmt.Println(s.age)
sp := &s
fmt.Println("sp: ", sp)
dog := struct {
name string
isGood bool
}{
"Rex",
true,
}
fmt.Println("dog: ", dog)
}
// 结构体
type person struct {
name string
age int
}
// 函数封装 实例化
func newPerson(name string, age int) *person {
p := person{name: name, age: age}
return &p
}
# 运行结果
zhangsan {zhangsan 22}
&{zhangsan 22}
lisi
24
sp: &{lisi 24}
dog: {Rex true}
这里涉及到了指针 后面会继续讲解 同时也会和c/c++ 的指针做对比
func main(){
const s = "สวัสดี"
fmt.Println("s: ", s, "\nLen:", len(s))
for idx, _ := range s {
//fmt.Printf("idx: ", idx, "runeValue: ", runeValue)
fmt.Printf("idx: %d, s[i]:%x\t", idx, s[idx])
}
fmt.Println("\nRnu count: ", utf8.RuneCountInString(s))
fmt.Println("\n===============")
for i, w := 0, 0; i < len(s); i += w {
runeValue, width := utf8.DecodeRuneInString(s[i:])
fmt.Printf("%#U start at byte position %d\n", runeValue, i)
w = width
examineRune(runeValue)
}
}
func examineRune(r rune) {
if r == 't' {
fmt.Println("found tee")
} else if r == 'ส' {
fmt.Println("found so sua")
}
}
# 运行结果
s: สวัสดี
Len: 18
idx: 0, s[i]:e0 idx: 3, s[i]:e0 idx: 6, s[i]:e0 idx: 9, s[i]:e0 idx: 12, s[i]:e0 idx: 15, s[i]:e0
Rnu count: 6
===============
U+0E2A 'ส' start at byte position 0
found so sua
U+0E27 'ว' start at byte position 3
U+0E31 'ั' start at byte position 6
U+0E2A 'ส' start at byte position 9
found so sua
U+0E14 'ด' start at byte position 12
U+0E35 'ี' start at byte position 15
分析 采用lens(s) 和 utf8.RuneCountInString(s)) 结果不同
前者返回的是 s 的字节长度(字符串的字节数)在utf-8编码下,每个unicode 字符可能由多个字节组成
utf8.RuneCountInString(s)) 返回的是字符串中字符数量。它会将字符串解释为Unicode码点序列,并计算这些码点的数量
%#U c/c++ 的占位符概念也用过来了, 这是用于格式化Unicode 字符,会输出一个完整的Unicode字符的完整描述
go interfaces
需要注意一点,go 的标准封装都是 大写开头
// 需要用到 Pi
import (
"math"
)
// #1 几何 求面积、求周长
type geometry interface {
area() float64
perim() float64
}
// # 2 rect 以及 circle实现 interface geometry
type rect struct {
width, height float64
}
type circle struct {
radius float64
}
func (r rect) area() float64 {
return r.width * r.height
}
func (r rect) perim() float64 {
return r.height*2 + r.width*2
}
func (c circle) area() float64 {
return math.Pi * c.radius * c.radius
}
func (c circle) perim() float64 {
return 2 * math.Pi * c.radius
}
# 3 interface geometry 的实现
func measure(g geometry) {
fmt.Println("g: ", g)
fmt.Println("g.area: ", g.area())
fmt.Println("g.perim: ", g.perim())
}
func main(){
// methods
r := rect{width: 10, height: 5}
m2 := circle{radius: 4.44}
ans := r.area()
fmt.Println("r area: ", ans)
tmp := r
fmt.Println("tmp perim : ", tmp.perim())
// r2 是 一个 rect 结构体对象,它将实现结构geometry,area()和perim()这两个方法都需要对象r2传入,
// 在调用measure,传入参数 r2,然后这个函数通过r2 实现了area()和perim(),注意这就是interface geometry的定义的所有方法
// 所以r2实现了interface geometry
// 其他的类比
r2 := rect{width: 22, height: 33}
c2 := circle{radius: 55}
measure(r2)
measure(c2)
measure(m2)
}
# 运行结果
r area: 50
tmp perim : 30
g: {22 33}
g.area: 726
g.perim: 110
g: {55}
g.area: 9503.317777109125
g.perim: 345.57519189487726
g: {4.44}
g.area: 61.93210093580775
g.perim: 27.897342763877365
//1
type I interface {
Get() int
Set(int)
}
//2
type S struct {
Age int
}
func(s S) Get()int {
return s.Age
}
func(s *S) Set(age int) {
s.Age = age
}
//3
func f(i I){
i.Set(10)
fmt.Println(i.Get())
}
func main() {
s := S{}
f(&s) //4
}
在这里例子中需要注意 f(&s) 是把s 的地址传入,也就是传的参数是指针。
因为在 func(s *S) Set(age int) 接收的是指针,当然你也会发现 func(s S)Get()int 接收的就是正常的s
为什么不能直接传入 s ? 你可以去测试,经过实践, 传入 会报错,提示需要传入指针
这里隐含一个知识点就是,go 中可以隐含的把指针转换成value!!!!!
interface{}
空的interface
有一点需要注意,go 中不能对interface{}进行切片转换
需要手动切换
==================================
更新 0425
对interface 的理解
//参考
var dataSlice []int = foo()
var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
for i, d := range dataSlice {
interfaceSlice[i] = d
}