Go Slice 使用


切片和数组很类似,甚至你可以理解成数组的子集。但是切片有一个数组所没有的特点,那就是切片的长度是可变的。
严格地讲,切片有容量(capacity)和长度(length)两个属性。
首先我们来看一下切片的定义。切片有两种定义方式,一种是先声明一个变量是切片,然后使用内置函数 make 去初始化这个切片。另外一种是通过取数组切片来赋值。

package main
    
import (
    "fmt"
)
    
func main() {
    var x = make([]float64, 5)
    fmt.Println("Capcity:", cap(x), "Length:", len(x))
    var y = make([]float64, 5, 10)
    fmt.Println("Capcity:", cap(y), "Length:", len(y))
    for i := 0; i < len(x); i++ {
        x[i] = float64(i)
    }
    fmt.Println(x)
    for i := 0; i < len(y); i++ {
        y[i] = float64(i)
    }
    fmt.Println(y)
}

输出结果为

Capcity: 5 Length: 5
Capcity: 10 Length: 5
[0 1 2 3 4]
[0 1 2 3 4]


阅读全文

Go Slice 底层实现


在 Go 中,与 C 数组变量隐式作为指针使用不同,Go 数组是值类型,赋值和函数传参操作都会复制整个数组数据。

func main() {
    arrayA := [2]int{100, 200}
    var arrayB [2]int

    arrayB = arrayA

    fmt.Printf("arrayA : %p , %v\n", &arrayA, arrayA)
    fmt.Printf("arrayB : %p , %v\n", &arrayB, arrayB)

    testArray(arrayA)
}

func testArray(x [2]int) {
    fmt.Printf("func Array : %p , %v\n", &x, x)
}

打印结果:

arrayA : 0xc4200bebf0 , [100 200]  
arrayB : 0xc4200bec00 , [100 200]  
func Array : 0xc4200bec30 , [100 200]

阅读全文

Go 计算 md5 值


主要是使用 crypto/md5、encoding/hex 两个包

字符串:

package process
    
import (
    "crypto/md5"
    "encoding/hex"
)
    
// MakeMD is make md5.
func MakeMD(initString string) string {
    m := md5.New()
    m.Write([]byte(initString))
    md := m.Sum(nil)
    mdString := hex.EncodeToString(md)
    return mdString
}

文件:

package main
    
import (
    "bufio"
    "crypto/md5"
    "fmt"
    "io"
    "os"

    "v.src.corp.qihoo.net/weblego/lib4go/convert"
)
    
func fileMdFir(filePath string) string {
    file, _ := os.Open(filePath)
    defer file.Close()
    h := md5.New()
    io.Copy(h, file)
    fileMd1 := convert.U2S(h.Sum(nil))
    return fileMd1
}
    
func fileMdSec(file string) string {
    f, _ := os.Open(file)
    defer f.Close()
    r := bufio.NewReader(f)
    h := md5.New()
    io.Copy(h, r)
    fileMd2 := convert.U2S(h.Sum(nil))
    return fileMd2
}
    
func main() {
    fileMd1 := fileMdFir("/tmp/conf/deploy.toml")
    fmt.Println(fileMd1)
    fileMd2 := fileMdSec("/tmp/conf/deploy.toml")
    fmt.Println(fileMd2)
}
阅读全文

Go 字符串删除


删除在 s 字符串的头部和尾部中由 cutset 指定的字符,并返回删除后的字符串。

func Trim(s string, cutset string) string

删除首部和尾部的 ! 和空格

// "Achtung! Achtung"
fmt.Printf("%q\n", strings.Trim(" !!! Achtung! Achtung! !!! ", "! "))
// "a lone gopher"
fmt.Printf("%q\n", strings.TrimSpace(" \t\n a lone gopher \n\t\r\n"))
阅读全文

Go 字符串拼接


1.直接使用运算符

func BenchmarkAddStringWithOperator(b *testing.B) {
    hello := "hello"
    world := "world"
    for i := 0; i < b.N; i++ {
        _ = hello + "," + world
    }
}

go 里面的字符串都是不可变的,每次运算都会产生一个新的字符串,所以会产生很多临时的无用的字符串,不仅没有用,还会给 gc 带来额外的负担,所以性能比较差。

2.fmt.Sprintf()

func BenchmarkAddStringWithSprintf(b *testing.B) {
    hello := "hello"
    world := "world"
    for i := 0; i < b.N; i++ {
        _ = fmt.Sprintf("%s,%s", hello, world)
    }
}

内部使用 []byte 实现,不像直接运算符这种会产生很多临时的字符串,但是内部的逻辑比较复杂,有很多额外的判断,还用到了 interface,所以性能也不是很。

阅读全文

Go 字符串分割


将字符串 s 以空格为分隔符拆分成若干个字符串,若成功则返回分割后的字符串切片。

str := "Hello World Too"
for _, v := range strings.Fields(str) {
    fmt.Println(v)
}

将字符串 s 中的字符串以字符 sep 为分隔符拆分成若干个元素的字符串切片,并返回字符串切片。

for _, v := range strings.Split(str, " ") {
    fmt.Println(v)
}

将字符串 s 中的字符串以字符 sep 为分隔符拆分成若干个字符串切片并且保留原字符串中的分隔符号,并返回字符串切片。

for _, v := range strings.SplitAfter(str, ",") {
    fmt.Println(v)
}
阅读全文

Go 字符串替换


package main
     
import (
    "fmt"
    "strings"
)
     
func main() {
    str := "welcome to beijing"
    strF = strings.Replace(str, " ", ",", -1)
    fmt.Println(strF)
    strS = strings.Replace(str, " ", ",", 1)
    fmt.Println(strS)
}

给定字符串转换为英文标题的首字母大写的格式,不能正确处理 unicode 标点。

func Title(s string) string

所有字母转换为小写。

func ToLower(s string) string

所有字母转换为大写。

func ToUpper(s string) string
// Her Royal Highness
fmt.Println(strings.Title("her royal highness"))
// gopher123
fmt.Println(strings.ToLower("Gopher123"))
// GOPHER
fmt.Println(strings.ToUpper("Gopher"))
阅读全文

Go 字符串查找


判断字符串 string 中是否有字符 chars,如果有返回 true,否则返回 false。

str := "Hello World"
fmt.Println(strings.Contains(str, "l"))
fmt.Println(strings.Contains(str, "T"))

判断字符串 string 中是否有字符 chars 中的任意一个字符,如果有返回 true,否则返回 false。

fmt.Println(strings.ContainsAny(str, "Wa"))
fmt.Println(strings.ContainsAny(str, "Ta"))

检查字符串 string 中字符 chars 出现的总次数。

fmt.Println(strings.Count(str, "l"))
fmt.Println(strings.Count(str, "T"))

阅读全文

Go 中 string int int64 float64 类型相互转换


主要使用包 strconv

package main
    
import "strconv"
    
func main() {
    // string to int
    int, _ := strconv.Atoi(string)
    // string to int64
    int64, _ := strconv.ParseInt(string, 10, 64)
    // string to float64
    float64, _ := strconv.ParseFloat(value, 64)
    // int to string
    string := strconv.Itoa(int)
    // int64 to string
    string := strconv.FormatInt(int64, 10)
}
阅读全文