本文目录一览:
- 1、golang排序问题求助
- 2、Golang database/sql源码分析
- 3、golang 结构体 字节对齐是怎么样的
- 4、请Golang深度用户说说,现在Golang的性能可以和C比吗
- 5、golang如何创建目录
- 6、golang 中结构体与字节数组能相互转化么
golang排序问题求助
如果是只有这几个的话 我们可以考虑自定义一个排序类型
func TestSort(t *testing.T) {
data := []string{"三级", "一级", "二级"}
rule := map[string]int{
"一级": 1,
"二级": 2,
"三级": 3,
}
self := SelfSort{
Rule: rule,
Data: data,
}
sort.Sort(self)
fmt.Println(self.Data)
}
type SelfSort struct {
Rule map[string]int
Data []string
}
func (p SelfSort) Len() int { return len(p.Data) }
func (p SelfSort) Less(i, j int) bool { return p.Rule[p.Data[i]] p.Rule[p.Data[j]] }
func (p SelfSort) Swap(i, j int) { p.Data[i], p.Data[j] = p.Data[j], p.Data[i] }
如过很多 就是真的要比较中文的话, 就用这种
package mainimport ( "bytes"
"fmt"
"io/ioutil"
"sort"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform")//ByPinyin is customized sort interface to sort string by Chinese PinYintype ByPinyin []stringfunc (s ByPinyin) Len() int { return len(s) }func (s ByPinyin) Swap(i, j int) { s[i], s[j] = s[j], s[i] }func (s ByPinyin) Less(i, j int) bool {
a, _ := UTF82GBK(s[i])
b, _ := UTF82GBK(s[j])
bLen := len(b) for idx, chr := range a { if idx bLen-1 { return false
} if chr != b[idx] { return chr b[idx]
}
} return true}//UTF82GBK : transform UTF8 rune into GBK byte arrayfunc UTF82GBK(src string) ([]byte, error) {
GB18030 := simplifiedchinese.All[0] return ioutil.ReadAll(transform.NewReader(bytes.NewReader([]byte(src)), GB18030.NewEncoder()))
}//GBK2UTF8 : transform GBK byte array into UTF8 stringfunc GBK2UTF8(src []byte) (string, error) {
GB18030 := simplifiedchinese.All[0]
bytes, err := ioutil.ReadAll(transform.NewReader(bytes.NewReader(src), GB18030.NewDecoder())) return string(bytes), err
}func main() {
b := []string{"哈", "呼", "嚯", "ha", ","}
sort.Strings(b) //output: [, ha 呼 哈 嚯]
fmt.Println("Default sort: ", b)
sort.Sort(ByPinyin(b)) //output: [, ha 哈 呼 嚯]
fmt.Println("By Pinyin sort: ", b)
}
copy from 网页链接
Golang database/sql源码分析
Gorm是Go语言开发用的比较多的一个ORM。它的功能比较全:
但是这篇文章中并不会直接看Gorm的源码,我们会先从database/sql分析。原因是Gorm也是基于这个包来封装的一些功能。所以只有先了解了database/sql包才能更加好的理解Gorm源码。
database/sql 其实也是一个对于mysql驱动的上层封装。”github.com/go-sql-driver/mysql”就是一个对于mysql的驱动,database/sql 就是在这个基础上做的基本封装包含连接池的使用
下面这个是最基本的增删改查操作
操作分下面几个步骤:
因为Gorm的连接池就是使用database/sql包中的连接池,所以这里我们需要学习一下包里的连接池的源码实现。其实所有连接池最重要的就是连接池对象、获取函数、释放函数下面来看一下database/sql中的连接池。
DB对象
获取方法
释放连接方法
连接池的实现有很多方法,在database/sql包中使用的是chan阻塞 使用map记录等待列表,等到有连接释放的时候再把连接传入等待列表中的chan 不在阻塞返回连接。
之前我们看到的Redigo是使用一个chan 来阻塞,然后释放的时候放入空闲列表,在往这一个chan中传入struct{}{},让程序继续 获取的时候再从空闲列表中获取。并且使用的是链表的结构来存储空闲列表。
database/sql 是对于mysql驱动的封装,然而Gorm则是对于database/sql的再次封装。让我们可以更加简单的实现对于mysql数据库的操作。
golang 结构体 字节对齐是怎么样的
作者:唐生
链接:
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
用golang解析二进制协议时,其实没必要管结构体的字段的对齐规则,何况语言规范也没有规定如何对齐,也就是没有规则。用encoding/binary.Read函数直接读入struct里就行,struct就像c那样写
type Data struct {
Size, MsgType uint16
Sequence uint32
// ...
}
golang编译器加不加padding,Read都能正常工作,runtime知道Data的布局的,不像C直接做cast所以要知道怎样对齐。
用unsafe.Alignof可以知道每个field的对齐长度,但没必要用到。
示例代码
package main
/*
#include stdint.h
#pragma pack(push, 1)
typedef struct {
uint16_t size;
uint16_t msgtype;
uint32_t sequnce;
uint8_t data1;
uint32_t data2;
uint16_t data3;
} mydata;
#pragma pack(pop)
mydata foo = {
1, 2, 3, 4, 5, 6,
};
int size() {
return sizeof(mydata);
}
*/
import "C"
import (
"bytes"
"encoding/binary"
"fmt"
"log"
"unsafe"
)
func main() {
bs := C.GoBytes(unsafe.Pointer(C.foo), C.size())
fmt.Printf("len %d data %v\n", len(bs), bs)
var data struct {
Size, Msytype uint16
Sequence uint32
Data1 uint8
Data2 uint32
Data3 uint16
}
err := binary.Read(bytes.NewReader(bs), binary.LittleEndian, data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%v\n", data) // {1 2 3 4 5 6}
buf := new(bytes.Buffer)
binary.Write(buf, binary.BigEndian, data)
fmt.Printf("%d %v\n", buf.Len(), buf.Bytes()) // 15 [0 1 0 2 0 0 0 3 4 0 0 0 5 0 6]
}
请Golang深度用户说说,现在Golang的性能可以和C比吗
不可以,完全没有可比性。
Golang的优势是开发速度,C可以自由、精准的操控内存。
拿string类型举个栗子:
1、修改字符串:
golang:需要分配新内存,然后进行内存copy。
c:可直接修改,可realloc。
2、存一段data:
golang:使用[]byte类型,[]byte转成string需要进行内存拷贝(排除掉利用指针进行类型转换的情况)。
c:直接用char[],可读可写。
golang中为了语言的安全性,类似的这种限制有很多,牺牲了一部分性能。但golang的优势也是显而易见的,goroutine、chan都很好用,而c则需要自己进行进程、线程的管控。
golang如何创建目录
golang中关于目录与文件名等操作都在os这个包中,具体的创建目录都是通过Mkdir和MkdirAll这2个函数来实现的,这两个函数用法一致
os.Mkdir(dirName string, perm FileMode)
dirName即要创建的目录(文件夹路径),可以是绝对路径,也可以是相对路径(相对于GOPATH)
perm表示创建的目录的权限,如0777(读r权限值为4,写权限w值为2,执行权限x值为1)
如:我要在/data/program/goapp这个目录下创建一个golang这个子目录,示例如下:
package main
import (
"os"
"fmt"
)
func main() {
err := os.Mkdir("/data/program/goapp/golang", 0666)
if err != nil {
fmt.Println(err)
}
}
注:Mkdir和MkdirAll的区别
Mkdir创建目录,它的父级目录必须是存在的,不然创建会失败
MkdirAll可以递归创建目录,即只要根目录存在即可,如下:
err := os.MkdirAll("/data/program/goapp/golang/test/hello", 0766)
if err != nil {
fmt.Println(err)
}
本例中:/data/program/goapp是已经存在的目录,而子目录golang/test/hello是不存在,此时要使用MkdirAll来创建
golang 中结构体与字节数组能相互转化么
结构体与[]byte不能直接转化,可以通过gob来转换。
编码时如下,假设默认的结构体为data
func Encode(data interface{}) ([]byte, error) { buf := bytes.NewBuffer(nil) enc := gob.NewEncoder(buf) err := enc.Encode(data) if err != nil { return nil, err } return buf.Bytes(), nil }解码时如下,data为需要解码的字节数组,to为相应的接收结构体,记住to的结构体结构应与被编码的data相一致,解码后内容保存在to里面,直接使用to即可
func Decode(data []byte, to interface{}) error { buf := bytes.NewBuffer(data) dec := gob.NewDecoder(buf) return dec.Decode(to) }使用的时候:
b, err := Encode(data) if err != nil { //错误处理 } if err := Decode(b, to); err != nil { //错误处理}