TonyChyi

我在那一角落患过抽风

用 Go 实现一个守护进程
2016年10月25日 文章
实现一个守护进程,同时还可以调用该程序加特定参数停止该守护进程 package main import ( "fmt" "io/ioutil" "os" "os/exec" "path/filepath" "strconv" "time" ) func main() { // 处理程序后的参数 if len(os.Args[1:]) > 0 { switch os.Args[1] { // 停止守护进程,从 /tmp/pidfile 中获取进程 ID case "stop": bpid, _ := ioutil.ReadFile("/tmp/pidfile") pid, _ := strconv.Atoi(string(bpid)) proc, _ := os.FindProcess(pid) proc.Kill() fmt.Println("Killed.") os.Exit(0) } } // 启动守护进程,即当自身的父进程不为 1 时,就启动一个新的进程, // 并退出自己,直到父进程为 1 (一般是 init)为止 if os.Getppid() != 1 { exePath, _ := filepath.Abs(os.Args[0]) cmd := exec.
Tags: #Go
实现一个类似RRDTool的算法
2016年05月06日 文章
RRDTool 中有一种算法: 每周的数据按每天汇总 每月的数据按每周汇总 每年的数据按每月汇总 或者说实现以下需求: 时间在三个月以内的,保留全部 时间在3-6个月的,每天保留一个 时间在6-9个月的,每周保留一个 基本的思路如下: 选取所定义的时间范围的所有内容a[],时间差为s 将a[0]定义为基准元素 遍历元素,与基准元素时间差< s的,删除 与基准元素时间差>= s的,该元素成为新的基准元素 以下是一个演示程序,生成一个1-100的数组,然后按照一定的策略删除(置0)其中的元素。 package main import ( "fmt" ) var a []int func init() { for i := 1; i <= 100; i++ { a = append(a, i) } } func main() { fmt.Println("Origin:", a, "\n") b := make([]int, 0) baseLine := a[0] // 基准值 for i, _ := range a { if i < 10 { b = append(b, a[i]) baseLine = a[i] continue } if i >= 10 && i < 30 { if a[i]-baseLine >= 2 { baseLine = a[i] // 更新基准值 b = append(b, a[i]) continue } a[i] = 0 } if i >= 30 && i <= 50 { if a[i]-baseLine >= 5 { baseLine = a[i] b = append(b, a[i]) continue } a[i] = 0 } if i >= 50 { if a[i]-baseLine >= 10 { baseLine = a[i] b = append(b, a[i]) continue } a[i] = 0 } } fmt.
Tags: #Go · #RRDTool
让 C 语言使用 Go 的回调函数
2016年02月06日 文章
在封装 XMMS2 的过程中我遇到了一个问题 typedef int (*xmmsv_list_compare_func_t)(xmmsv_t **, xmmsv_t **); int xmmsv_list_sort (xmmsv_t *listv, xmmsv_list_compare_func_t comparator) XMMS_PUBLIC; 这货居然用了回调(Callback)! 于是我尝试直接将 Go 函数的地址传给 C 代码,结果只有一个,段错误。因为 Cgo 只对打过 //export 注释的函数建立调用的 Stub 终于我还是在 Stack Overflow 的这个问题中受到了启发。 不要尝试直接调用 Go 函数,而是通过一个已经导出的函数间接的去调用它。 于是我写了一个名叫 callback 的包。 package callback /* void doTest(int); typedef void (*callback)(int); // 模拟一个需要 callback 的函数 static void real_func(callback func){ func(9); // BAKA } static void real_func_wrapper(){ real_func(doTest); } */ import "C" import "sync" type CallbackFunc func(int) // 关键就在这里,需要设置一个全局变量 var w CallbackFunc func init() { w = func(i int){} } //export doTest func doTest(i C.
Tags: #Go · #C
基于libxmmsclient的Go语言绑定
2016年01月14日 文章
代码:[email protected] 文档:[email protected] 在我发现 XMMS2 是使用了 C/S 架构以后,就有了一个想法: 用 Go/QML/XMMS2 写一个简单的音乐播放器,顺带可以收听网易云音乐 XMMS2 有很多种前端,从桌面到 Web 页面什么都有,然而大部分项目长期不更新了。 XMMS2 官方支持的语言有:C/C++/Python/Perl/Ruby。嗯,没有 Go 从上个周末开始,我尝试用抓包的方法来分析 XMMS2 的通讯协议,一无所获。 代码就很复杂了,还是二进制的协议,这怎么搞嘛! 不要重复造轮子!不要重复造轮子!不要重复造轮子! 重要的事情说三遍 显然更讨巧的办法是做一个绑定。 一开始我就有了下面这一套代码 package xmms2go /* #cgo CFLAGS: -I/usr/include/xmms2 #cgo LDFLAGS: -lxmmsclient #include <xmmsclient/xmmsclient.h> */ import "C" import ( "errors" "fmt" ) type Xmms2Client struct { Connection *X.xmmsc_connection_t result *C.xmmsc_result.t returnValue *C.xmmsv_t errorBuff *C.char } func NewXmms2Client(clientName string) (*Xmms2Client, error) { x := new(Xmms2Client) x.
Tags: #Go · #Xmms2 · #C
[转]Golang中的“泛型”支持
2016年01月08日 文章 · 转载
来源 Golang不支持一般的类似java中的标记式泛型。很多人因此而十分不满,认为没有泛型增加了很多工作量。而目前由于泛型支持的复杂性,Golang的设计和实现者并没有把这个泛型支持作为紧急需要增加的特性。但是,如果真的没有泛型,就一定不行了么?答案当然是否定的。没有泛型也可以,而且我觉得代码更简单,直接,有趣(个人观点,勿喷)。 我们这里打算以一些例子来讲解Golang中如何处理这个问题。 首先,我们看一个冒泡排序的问题。针对整型数组切片的排序。 package main import ( "fmt" ) func bubbleSort(array []int) { for i := 0; i < len(array); i++ { for j := 0; j < len(array)-i-1; j++ { if array[j] > array[j+1] { array[j], array[j+1] = array[j+1], array[j] } } } } func main() { a1 := []int{3, 2, 6, 10, 7, 4, 6, 5} bubbleSort(a1) fmt.Println(a1) } 上面的例子输出为: [2 3 4 5 6 6 7 10] 那么,我们如果希望这个bubbleSort能够同时支持float类型数据排序,或者是按照字符串的长度来排序应该怎么做呢?在其他的例如java语言中,我们可以将bubbleSort定义为支持泛型的排序,但是Go里面就不行了。为了达到这个目的,我们可以使用interface来实现相同的功能。
Tags: #Go · #泛型
Go的异步UDP服务器
2015年11月25日 文章
package main import( "net" "fmt" "strings" "runtime" ) type Data struct{ C string D *net.UDPAddr } func main(){ runtime.GOMAXPROCS(runtime.NumCPU()) addr, err := net.ResolveUDPAddr("udp", ":25252") // Niconiconi~ if err != nil{ fmt.Println("!ERR:", err) return } conn, err := net.ListenUDP("udp", addr) if err != nil{ fmt.Println("!ERR:", err) return } defer conn.Close() c := make(chan Data, 1024) // 带缓冲的通道 fmt.Println("Listen at 25252") for { data := make([]byte, 1024) read, fAddr, err := conn.ReadFromUDP(data) if err !
Tags: #Go · #Server

 

TonyChyi © 2018 GPLv2