go | struct、pointer、strings& runes、interfaces

15 篇文章 0 订阅

更新,好吧最开始照着官方文档写的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++ 的指针做对比

go 关于 符文的介绍
go strings

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
}
  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
非常抱歉,我的回答有误。在我的上一个回答中,我将结构体对象 `obj` 与成员指针相加是错误的。正确的做法是需要使用 `reinterpret_cast` 将结构体对象的地址转换为 `int*` 类型,然后再进行指针加法运算。下面是修改后的示例代码: ```cpp #include <iostream> #include <string> #include <typeinfo> using namespace std; template <typename T, typename U> struct member_pointer_type { typedef U T::*type; }; template <typename T, typename U> typename member_pointer_type<T, U>::type get_member_pointer(U T::*member) { return member; } template <typename T> void print_member_values(const T& obj) { const int num_members = sizeof(T) / sizeof(int); int* obj_ptr = reinterpret_cast<int*>(&obj); for (int i = 0; i < num_members; ++i) { typedef typename member_pointer_type<T, int>::type member_pointer; member_pointer member_ptr = get_member_pointer(&T::*(obj_ptr + i)); const char* member_name = typeid(member_ptr).name(); cout << member_name << ": " << obj.*member_ptr << endl; } } struct Person { int age; string name; }; int main() { Person p = { 30, "Tom" }; print_member_values(p); return 0; } ``` 在这个示例代码中,我们使用 `reinterpret_cast` 将结构体对象 `obj` 的地址转换为 `int*` 类型,并将其存储在 `obj_ptr` 变量中。然后,我们使用指针加法运算来获取结构体的每个成员指针,并使用 `.*` 运算符来访问结构体的成员值。 希望这个修正能够帮助到您。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值