总结:golang记录

一、interface{}

golang中可以使用interface{}表示任何类型。

其实和java中的interface几乎一样,也是接口,需要实现类

二、strconv包

strconv包实现了基本数据类型与其字符串表示的转换,主要有以下常用函数:
Atoi()Itia()、parse系列、format系列、append系列。

案例:

netIf.InBytes, _ = strconv.ParseInt(fields[0], 10, 64)
netIf.InPackages, _ = strconv.ParseInt(fields[1], 10, 64)
netIf.InErrors, _ = strconv.ParseInt(fields[2], 10, 64)
netIf.InDropped, _ = strconv.ParseInt(fields[3], 10, 64)
netIf.InFifoErrs, _ = strconv.ParseInt(fields[4], 10, 64)

strconv.ParseInt(fields[0], 10, 64):将字符串转为数字,并且限制数字大小不能超过int64的最大值

golang strconv.ParseInt 是将字符串转换为数字的函数,功能非常强大.

参数1 数字的字符串形式
参数2 数字字符串的进制 比如二进制 八进制 十进制 十六进制
参数3 返回结果的bit大小 也就是int8 int16 int32 int64

三、io/ioutil包

读文件,比如linux的一些网卡的监控,需要读取文件:/proc/net/dev

golang读取:

    contents, err := ioutil.ReadFile("/proc/net/dev")

	ret := []*NetIf{}

	reader := bufio.NewReader(bytes.NewBuffer(contents))
	for {
		lineBytes, err := file.ReadLine(reader)

		line := string(lineBytes)
		idx := strings.Index(line, ":")
		if idx < 0 {
			continue
		}

		netIf := NetIf{}

		eth := strings.TrimSpace(line[0:idx])
		if len(onlyPrefix) > 0 {
			found := false
			for _, prefix := range onlyPrefix {
				if strings.HasPrefix(eth, prefix) {
					found = true
					break
				}
			}

			if !found {
				continue
			}
		}

		netIf.Iface = eth
		fields := strings.Fields(line[idx+1:])

		netIf.InBytes, _ = strconv.ParseInt(fields[0], 10, 64)
		netIf.InPackages, _ = strconv.ParseInt(fields[1], 10, 64)

		ret = append(ret, &netIf)
	}

四、golang中的strings.Index

golang字符串操作

strings.Index(s,str):返回子串str在字符串s中第一次出现的位置。如果找不到则返回-1;如果str为空,则返回0

func main(){
        s := "hello world hello world"
        str := "wo"
 
        //返回子串str在字符串s中第一次出现的位置。
        //如果找不到则返回-1;如果str为空,则返回0
        index := strings.Index(s,str)
        fmt.Println(index) //6
}

五、Golang之缓冲器bytes.Buffer

b := bytes.NewBuffer(s []byte) //从一个[]byte切片,构造一个Buffer

六、go中string与[]byte的互换

1、标准转换

标准转换方式:

	// string to []byte
	s1 := "hello"
	b := []byte(s1)
	
	// []byte to string
	s2 := string(b)

2、强转换

通过unsafe和reflect包,可以实现另外一种转换方式,我们将之称为强转换(也常常被人称作黑魔法)。

func String2Bytes(s string) []byte {
	sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
	bh := reflect.SliceHeader{
		Data: sh.Data,
		Len:  sh.Len,
		Cap:  sh.Len,
	}
	return *(*[]byte)(unsafe.Pointer(&bh))
}

func Bytes2String(b []byte) string {
	return *(*string)(unsafe.Pointer(&b))
}

强转换方式的性能会明显优于标准转换。

七、字符串截取

  • 可以使用len(字符串变量)获取字符串的字节长度,其中英文占1个字节长度,中文占用3个字节长度

  • 可以使用变量名[n]获取到字符串第n+1个字节,返回这个字节对应的Unicode码值(uint8类型).注意n的取值范围是[0,长度)

  • 可以使用变量名[n:m]取出大于等于n小于m的字符序列

    • n和m都可以省略,省略时认为n为0,m为长度

    • 因为中文占用三个字节,如果没有把中文完整取出,会出现乱码

func main() {
    s := "smallming张"
    fmt.Println(len(s)) //输出:12,字节长度,注意,中文三个字节
    fmt.Println(s[1:4]) //输出:mal
    fmt.Println(s[:2])  //输出:sm
    fmt.Println(s[5:])  //输出:ming张
}

八、strings.Fields函数

以连续的空白字符为分隔符,将s切分成多个子串,结果中不包含空白字符本身。

返回str的子字符串切片

func main(){
        s := "hello world hello world"
        //str := "wo"
 
        //以连续的空白字符为分隔符,将s切分成多个子串,结果中不包含空白字符本身。
        //空白字符有:\t, \n, \v, \f, \r, ’ ‘, U+0085 (NEL), U+00A0 (NBSP) 。
        //如果 s 中只包含空白字符,则返回一个空列表
        index := strings.Fields(s)
        fmt.Println(len(index)) //4
}

九、关于生成对象

我们一般用new或&去生成对象,他们生成的对象就是指针类型

netIf := &NetIf{}:netIf就是一个指针,指向对象的内存地址

netIf := NetIf{}:netIf则表示对象本身而不是指针

但是对netIf的使用上几乎没有区别,那为什么要有两种方式呢?

主要是指针的话方法传递的时候,直接传递的是指针,这个好处是空间小,尤其是分布式开发的时候,最好用指针

而调用方法直接传递对象的话就是传递对象本身了,对于分布式方法调用,会导致传递的流量变大

十、Golang 内置函数:make()

make() 是 Go 语言内存分配的内置函数,默认有三个参数。

make(Type, len, cap)
Type:数据类型,必要参数,Type 的值只能是 slice、 map、 channel 这三种数据类型。
len:数据类型实际占用的内存空间长度,map、 channel 是可选参数,slice 是必要参数。
cap:为数据类型提前预留的内存空间长度,可选参数。所谓的提前预留是当前为数据类型申请内存空间的时候,提前申请好额外的内存空间,这样可以避免二次分配内存带来的开销,大大提高程序的性能。

十一、golang调用函数

golang中函数可以不属于任何一个结构体,可以用包直接调用,如:

netIfs, err := nux.NetIfs(ifacePrefix)

nux是个包,包直接调用了函数,github.com/toolkits/nux

而Java中必须先创建对象,再通过对象调用函数

十二、函数名之前指定接收者

读Grafana mimir源码的时候,看到了如下的函数,func后面跟了一个括号,一开始以为是返回值,但是golang返回值定义在参数后面,后来咨询了下chatgpt。

原来,这是一个接收者,其实就是什么类型可以调用这个方法,比如下面的函数,其实就是 *Limits的 l ,可以直接调用下面的方法,如本例中:l.unmarshal(func(v any) error {

func (l *Limits) UnmarshalJSON(data []byte) error {

    return l.unmarshal(func(v any) error {

        xxx

    })
}


func (l *Limits) unmarshal(decode func(any) error) error {

    xxx

}

下面是chatgpt的回答:

在 Go 语言中,接收者是将方法(成员函数)与特定的数据类型关联起来的一种机制。接收者就是方法执行时所作用于的数据类型的实例,可以将其理解为其他面向对象编程语言(如 Java)中的 `this` 或 `self` 关键字。

接收者为函数添加了一个隐式的第一个参数,而这个参数代表了调用此方法的数据类型的实例。当你在这个实例上调用方法时,接收者参数会自动传递给该方法。

以下是一个详细解释接收者用法的例子:

```go
package main

import (
    "fmt"
)

// 定义一个简单的结构体,用于表示人的姓名和年龄。
type Person struct {
    Name string
    Age  int
}

// 接收者是 Person 结构的 方法。它在 Person 类型的实例上打印 "Hello" 消息。
func (p Person) SayHello() {
    fmt.Println("Hello, my name is", p.Name)
}

// 带有接收者的方法,它在 Person 类型的实例上增加年龄。
func (p *Person) AddAge(years int) {
    p.Age += years
}

func main() {
    // 创建一个 Person 结构体实例
    person := Person{Name: "Alice", Age: 30}

    // 使用接收者在 person 实例上调用 SayHello 方法
    person.SayHello() // 输出 "Hello, my name is Alice"

    // 使用接收者在 person 实例上调用 AddAge 方法
    person.AddAge(5) // person.Age 变为 35

    fmt.Println("Person after adding 5 years:", person)
}
```

在示例中,我们定义了一个名为 `Person` 的结构体,并为其实现了两个方法:`SayHello` 和 `AddAge`。这两个方法都具有接收者参数,它们指定了这些方法应作用于哪种数据类型。

`SayHello` 方法的接收者是 `Person` 类型,其方法签名为 `func (p Person) SayHello()`。这表示只要有一个 `Person` 类型的实例,我们就可以在这个实例上调用 `SayHello` 方法。

`AddAge` 方法的接收者是 `*Person` 指针类型,其方法签名为 `func (p *Person) AddAge(years int)`。由于接收者类型是指针,当在 `Person` 实例上调用 `AddAge` 方法时,我们可以直接修改这个实例的状态(即修改其 `Age` 属性)。

在 `main` 函数中,我们创建了一个名为 `person` 的 `Person` 类型实例,并在该实例上调用了这两个方法。

总结一下,接收者的用法主要是为了将方法与特定的数据类型关联。在方法内部可以通过接收者参数访问和操作数据类型的实例。带有接收者的方法可以在其数据类型的实例上调用,接收者参数会自动传入方法内。

十三、结构体定义:标签

如下结构体第三列,这是golang对结构体的支持,即标签,指从某种格式的文件中获取key对应的value值。

结构体标签被放置在反引号 (``) 中,紧跟字段类型之后。标签的格式通常是 `key:"value"`

key如JSON、YAML、XML 等。

以下定义了yaml和json两个,即从yaml中取或从json中取request_rate的值。

type Limits struct {
	// Distributor enforced limits.
	RequestRate               float64             `yaml:"request_rate" json:"request_rate" category:"experimental"`
	RequestBurstSize          int                 `yaml:"request_burst_size" json:"request_burst_size" category:"experimental"`
	IngestionRate             float64             `yaml:"ingestion_rate" json:"ingestion_rate"`

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值