![](https://img-blog.csdnimg.cn/20201014180756925.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
go
maxdaic
这个作者很懒,什么都没留下…
展开
-
slice的浅拷贝和深拷贝
以前学c++的时候就知道有深拷贝和浅拷贝,主要是涉及到指针的拷贝。浅拷贝就是只拷贝指针的值,指针指向的内容只有一份。而深拷贝是把指针指向的值拷贝一份,这样指向这段数据的指针的值也要跟着改变了。golang里面也有浅拷贝和深拷贝。slice的浅拷贝就是指slice变量的赋值操作。slice的深拷贝就是指使用内置的copy函数来拷贝两个slice。实例代码如下所示:func main() { SliceShallowCopy() SliceDeepCopy()}func Slic原创 2020-07-23 15:03:38 · 3394 阅读 · 0 评论 -
Golang的unsafe.Pointer是真的不安全
今天看了一篇文章,介绍通过指针的方式在类型强转的过程中避免数据拷贝。代码如下:a :="aaa"ssh := *(*reflect.StringHeader)(unsafe.Pointer(&a))b := *(*[]byte)(unsafe.Pointer(&ssh))fmt.Printf("%T",b)fmt.Printf("%v",b)原理就是,内置string类型其实本质是个reflect.StringHeader,内置切片类型其本质其实是reflect.Slic原创 2020-07-23 11:33:16 · 1035 阅读 · 0 评论 -
最简单的P2P加密聊天软件开发完成
昨天花了点时间做了一个最简单的P2P加密聊天软件。代码很少,功能很简单,暂时只能吃两个人聊,也暂时没有动力去做扩展,做这个的初衷也只是为了锻炼自己用golang写代码的熟练程度,以及对AES对称加密和ECDSA密钥交换算法的应用还好,很顺畅,没遇到太大的阻碍。下面是效果,只能在控制台下输入和打印聊天信息也软件日志,红√勾出来的是聊天内容,其他的是日志信息。代码已上传到github,开源地址:https://github.com/lilianwen/P2P-Crypto-Chat...原创 2020-07-21 16:59:02 · 1533 阅读 · 0 评论 -
golang的sync.Map是残缺的
今天用了一下golang的sync.Map,但是让我感到很蛋疼的地方在于,我发现这个东西,这个官方提供的东西,居然有个很大的功能是残缺的!!!那就是获取map中元素的个数。像普通的map,直接使用len()就可以测量出当前map的键值对的个数。但是sync.Map是一个封装好的产品,不能使用len(),也没有提供输出的接口告诉使用者当前里面的元素的个数。当然也可以自己去改代码,或者自己依赖sync.Map创建新的类型,自己实现这个接口,但那毕竟不是很方便。这样一个官方推出的东西居然有这样一个问题原创 2020-07-19 01:00:40 · 325 阅读 · 0 评论 -
golang的error wrapping
我们都知道error用处特别多,但是golang官方提供的error类型功能实在太单一了,只能打印错误提示字符串。不过在Go1.13版本后对error功能进行了增强,也就是今天要提到的error wrapping。error wrapping的原理非常简单,通过fmt.Errorf + %w的组合生成一个嵌套的error。通过多次调用生成多层嵌套error。同时errors包还提供了三个好用的函数,全列在下面的图里。最后我写了个demo测试了一下,确实很好用:type MyError原创 2020-07-18 03:07:15 · 1357 阅读 · 0 评论 -
golang的一个让人不解的bug
今天写代码遇到一个很奇葩的问题,我一直觉得没有语法错误的地方,偏偏居然有语法错误:mgr.dbUtxo, err := leveldb.OpenFile(cfg.DataDir+"/blockchain/utxo",nil)错误提示如下图:把上面的代码改成下面这样就OK了var err errormgr.dbUtxo, err = leveldb.OpenFile(cfg.DataDir+"/blockchain/utxo",nil)真是见鬼了,以前没遇到过这种情况。哦觉得原创 2020-07-14 11:33:56 · 263 阅读 · 1 评论 -
学习go语言内置的gob编码——编码后的数据长度
go语言内置了gob这种编码方案,我从来没用过,感觉很好奇,今天试试。先写一个简单的代码体验一下:type Retangle struct { Length uint8 Width uint8}func main() { r := Retangle{ 20, 18, } var buffer bytes.Buffer encoder := gob.NewEncoder(&buffer) err := encoder.Encode(&r) .原创 2020-07-12 02:40:33 · 670 阅读 · 0 评论 -
用container/heap实现一个最小堆
很少用container/heap这个工具,今天看到别人用来实现一个最小堆,感觉很有意思哈。代码如下:type Request struct { fn func() int data []byte op int c chan int}type Worker struct { req chan Request pending int index int done chan struct{}}type Pool []*Workerfu原创 2020-07-11 03:31:14 · 168 阅读 · 0 评论 -
简单二分查找-golang
又是程序员小灰的漫画,关于二分查找的,我写了个简单的实现。不过实际写代码的过程中并不一帆风顺,有些特殊情况还是没有考虑到。下面是源码:var ( ErrNotFound = errors.New("not found target"))func BinarySearch(data []int, target int) (int,error) { dataAmount := len(data) if dataAmount == 0 { return 0, ErrNotFound原创 2020-07-10 21:14:42 · 148 阅读 · 0 评论 -
简单插入排序-golang
看了程序员小灰的插入排序漫画,还是很好理解的。我当初上大学的时候能有这么好的学习资料就好了。下面是我自己用golang实现的插入排序算法func InsertSort(data []int) { var dataAmount = len(data) for i:=1; i<dataAmount; i++ { target := data[i] for j:=i-1; j >=0; j-- { if data[j] > target { data[j+原创 2020-07-10 20:10:05 · 133 阅读 · 0 评论 -
golang处理系统信号
今天学了一下golang处理系统信号。和在后台开发来说,应该是个很常规的操作。先定义一个通道sigs ,用来和系统交互,系统把信号存放在这个通道里面,怎么让系统知道要存放到这个通道里呢?调用系统函数:signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)后面两个是我们定义的要捕获的信号。也就是说系统会将这两种信号捕获给我们的程序,其他的信号不会捕获给我们,除非我们继续注册其他的信号。接下来,我们要开一个goroutine专门用来等待系.原创 2020-07-06 02:50:13 · 543 阅读 · 0 评论 -
golang内置的log
今天学习了一下golang内置的log实现,有点小收获。先来看看它是怎么用的。import "log"func main() { log.SetPrefix("[logusage]") log.SetFlags(log.Ldate|log.Llongfile) log.Println("i am log") log.Fatalln("i am fatal") log.Panicln("i am panic")}log提供的接口也不多,最基础的用法就那几个函数。log..原创 2020-07-11 12:01:45 · 835 阅读 · 0 评论 -
go get无法访问github怎么办?
在控制台下输入go get github.com/xxx/xxx结果提示访问github.com超时。虽然我的浏览器可以通过sock5代理访问github.com,但是控制台不行。后来找到一个简单的解决方案:在win10系统里设置两个环境变量:设置好环境变量后,重启控制台即可访问github.com。...原创 2020-06-30 12:39:42 · 3946 阅读 · 3 评论 -
类型别名和类型定义
看到一段代码type IntAlias = int觉得很好奇,怎么中间有个=,搞得跟赋值语句似的。这是什么语法?原来这是类型别名,跟类型定义不同。在Go1.9以前声明类型别名的时候是没有=的,Go1.9以后就有了。所以我以前看到的代码都是老代码,而且我也一直那样写。我一直是用类型定义,从来没用过类型别名。类型别名拥有之前类型的方法,但类型定义不行。例如,你可以这样写代码// 定义商标结构type Brand struct {}// 为商标结构添加Show方法func原创 2020-06-30 12:40:54 · 711 阅读 · 0 评论 -
go语言实现最短路径走迷宫算法
今天看了一个介绍走迷宫算法的视频,就自己动手写了一遍。写一篇日志以免将来忘记。首先是迷宫的表示。如左下图,起始位置是左上角黄色位置,重点位置是右下角黄色位置。在这个二维矩阵里,0表示道路通畅,可走;1表示有障碍物,不可走。最终计算出来的结果如右下角所示,从左上角0开始,每走一步,累加一次,这样就可以显示出整条路径的先后顺序。要走最短路径,只要从终点位置,不断递减1寻找上一步的位置直到回到起始位置即可。算法的主要过程:从矩阵中一点向外探索,总共有四个方向,分别是上下左右,如下图。当探索原创 2020-06-29 14:39:22 · 737 阅读 · 0 评论 -
golang实现简单的布隆过滤器
关于布隆过滤器的概念性的介绍,我就不多做解释了,可以详细查看一下文章最后的那篇参考资料。我实现这个布隆过滤器是从三个公式开始的,如下图所示只有先处理好这些布隆过滤器的参数以后,才方便创建一个布隆过滤器。三个计算公式对应的实现代码如下:// 计算布隆过滤器位图大小// elemNum 元素个数// errorRate 误判率func CalBloomSize(elemNum uint64, errRate float64) uint64 { var bloomBitsSize = f原创 2020-06-27 01:40:12 · 873 阅读 · 0 评论 -
goconvey的使用
今天试用了一下goconvey,结果就掉坑里去了。网上看了很多网友写的教程,都是坑。其中最大的坑,是没有任何人提到如何用浏览器查看我自己写的项目的测试结果。go test那肯定是没问题的。启动goconvey的http服务也是没问题的。但是在浏览器里看不到我的项目的测试用例啊。这怎么搞?没人说啊,我也不知道其他人怎么那么顺利,到我这里就不灵了。还是得靠自己摸索。最后我摸索出合理的goconvey使用方法: goconvey.exe -workDir ../src/golan原创 2020-06-22 20:45:58 · 563 阅读 · 0 评论 -
go语言的new和make有什么不同?
golang中的new和make有什么不同?golang中好像很少用到new这个内建函数,但是make却用得很频繁。我只用过一次。new(big.Int).SetBytes(...)new用来给指针分配内存并将分配的内存空间初始化为零值,通常都用来分配值类型内存空间。有没有给引用类型指针分配内存空间。可能有这种应用场景,但我没有遇到过。make用于初始化引用类型,如slicemapchannel而且非它不可。下面我要尝试用new给引用类型分配内存。..原创 2020-06-20 00:00:35 · 144 阅读 · 0 评论 -
base58编码与解码实现
Base58编码是比特币地址生成算法中的最后一个步骤。算法简单,和上大学时候学过的十进制转十六进制一样,只不过现在变成了十进制转58进制,核心过程就是不断的除58求余。下面是Go语言的实现过程:func Base58Encode(data []byte) string { var ( alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" bigNum = new(big.Int).SetBytes(da原创 2020-06-19 11:19:45 · 2173 阅读 · 0 评论 -
原来日志级别都有标准规定
最近在看go web编程方面的东西,其实就是beego了。然后我看到源码里有这么一行代码:// RFC5424 log message levels.const ( LevelEmergency = iota LevelAlert LevelCritical LevelError LevelWarning LevelNotice LevelInformational LevelDebug)我有点懵了,没想到日志级别都有标准规定:RFC5424。好奇心的驱使下去看了一下原创 2020-06-11 00:29:31 · 538 阅读 · 0 评论 -
go web编程由浅入深4——实现一个简单静态文件服务器
实现一个简单的静态服务器,代码很简单,只需要在前面的代码里增加以下几行代码即可:pwd ,err := os.Getwd();if err != nil { panic(err)}mux.Handle("/static",http.StripPrefix("/static", http.FileServer(http.Dir(pwd))))这样就简单实现了一个静态文件服务器。完整代码如下:package mainimport ( "io" "net/http" "os"原创 2020-06-10 14:23:15 · 128 阅读 · 0 评论 -
go web编程由浅入深3——用我们自定义的Server
还记得之前有个http.ListenAndServe吗,现在来看看它的定义:func ListenAndServe(addr string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServe()}可以看出,原来内部是实现了一个Server结构体,然后调用这个结构体对象的ListenAndServe函数。下面我们就自己来实现一个Ser原创 2020-06-10 13:32:03 · 222 阅读 · 0 评论 -
go web编程由浅入深2——用我们自定义的ServeMux
上一篇文章我们看到go的http库底层默认用的一个ServeMux对象来处理路由。现在我们要自己实现一个简单的ServeMux来取代底层默认的ServeMux对象。代码如下:package mainimport ( "io" "net/http")func main() { mux := http.NewServeMux() mux.HandleFunc("/hi", sayHi) mux.Handle("/", &MyHandler{}) if err := http.原创 2020-06-10 12:44:33 · 591 阅读 · 0 评论 -
go web编程由浅入深1——注册简单handler函数
这个小系列我打算彻底弄懂golang的Http库,一点一滴慢慢深入。下面是最简单的go web编程例子。通过把一个简单的函数注册到http服务器的路由中去。package mainimport ( "io" "net/http")func main () { http.HandleFunc("/", sayHi) if err := http.ListenAndServe("127.0.0.1:8080", nil); err != nil { panic(err) }}原创 2020-06-10 12:22:03 · 345 阅读 · 0 评论 -
golang练习之聊天室——服务端增加日志文件和客户端命令功能
前面我们实现了大部分聊天室的功能,但有个核心的功能没做好,那就是每个客户端无法显示当前在线的客户有哪些。现在我们就增加这个功能。在客户端和服务端之间的网路协议增加一条:当客户端和网络端用*隔开的时候,就表示客户端要向服务端发送命令,现在暂定命令是members,然后服务端就向客户端发送当前所有在线客户的列表。在增加一个实用的功能,那就是服务端把日志写到日志文件里面去。当然,前面的例子只实现了客户端之间通信,根本没有实现聊天室群通信的功能,在这里实现了。sever代码package原创 2020-06-10 09:18:02 · 247 阅读 · 0 评论 -
golang练习之聊天室——服务端增加消息转发功能
上一篇我们完成了客户端和服务端不停地发送接收消息的功能,接下来,我们要给服务端增加一个功能:在客户端端之间做消息转发。要实现消息转发,首先要有客户列表。这个列表表示当前在线的客户,这样更容易实现。这可以在客户端连上来的时候就保存客户的信息。客户之间发送消息的时候,用#隔开,前面是要发送到的客户端的ip和端口,后面是消息的内容。代码如下:package mainimport ( "errors" "github.com/apex/log" "net" //"github.com/de原创 2020-06-10 09:19:27 · 298 阅读 · 0 评论 -
golang练习之聊天室——丰富客户端功能
前面一篇设计的客户端太简陋了,只向服务端发送一个hello world就退出了。现在我们要丰富一下客户端的功能。让客户端不仅能向服务端发送数据,也能接收服务端发送过来的数据。server代码:package mainimport ( "github.com/apex/log" "net")func handleOneClient(client net.Conn) { defer client.Close() buf := make([]byte, 1024) for { n原创 2020-06-10 09:19:06 · 169 阅读 · 0 评论 -
golang练习之聊天室——基本通信
今天开始练习用golang写网络服务了,首先就拿聊天室来练手吧。先试试基本的通信,熟悉一下基本的API。server端代码:package mainimport ( "github.com/apex/log" "net")//我靠,为什么不能用指针调用接口,这是什么骚设计?//func handleOneClient(client *net.Conn) {func handleOneClient(client net.Conn) { buf := make([]byte,原创 2020-06-10 09:18:48 · 181 阅读 · 0 评论 -
cgo的简单尝试
研究ethereum源码的时候,运行其椭圆曲线签名算法提示我错误,说是找不到gcc。然后我就安装好gcc。我想这是用go源码调用c代码啊,好像是一个叫cgo的功能来者。好奇心的驱动下,写了两个demo感受了一下。C代码直接写在go源码里package main/*#include <stdio.h>int Sum(int a, int b){ return a+b;}*/import "C"import "fmt"func main(){ var a, b原创 2020-06-08 02:39:39 · 213 阅读 · 0 评论