golang开发博客的一些经验总结

mebiusashan · 2017-11-26 07:08:37 · 4135 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2017-11-26 07:08:37 的主题,其中的信息可能已经有所发展或是发生改变。

原文链接:https://ashan.org/archives/932

国庆节时,用大约9天时间借助golang重写编写了博客系统的前台部分,由于系统的特殊性,这部分完成后只能说完成了整套系统1/3的功能。十一回来后,又用了大约10天时间,每天写一点,完成了系统余下的两部分内容。由于是第一次用golang开发服务器内容,所以踩得坑不少,这里做一个总结。

函数传值问题

这个问题不算难,一开始看文档的时候已经注意到了,但没太在意。因为很多逻辑代码都是照搬旧版Nodejs版本来写的,所以就更加忽略了这个问题。知道本地命令操作时间略长,我才感觉不对劲。

举一个简单的例子:

package main

import (
    "fmt"
    "time"
)

func main() {
    _abc()
}

func _abc() {
    fmt.Println("start")
    starttime := time.Now()
    var data Tt
    for i := 0; i < 10000; i++ {
        Set(data)
    }
    fmt.Println(time.Since(starttime))

}

type Tt struct {
    Name     string
    Age      int
    Email    string
    Addr     string
    Nickname string
}

func Set(data Tt) Tt {
    data.Name = "ashan"
    data.Age = 32
    data.Email = "abc@abc.com"
    data.Addr = "china"
    data.Nickname = "ashan"
    return data
}

上面这段代码运行起来需要大约214.323µs。在1ms内完成了,我们稍微修改一下代码再来运行一次。

package main

import (
    "fmt"
    "time"
)

func main() {
    _abc()
}

func _abc() {
    fmt.Println("start")
    starttime := time.Now()
    var data Tt
    for i := 0; i < 10000; i++ {
        Set(&data)
    }
    fmt.Println(time.Since(starttime))

}

type Tt struct {
    Name     string
    Age      int
    Email    string
    Addr     string
    Nickname string
}

func Set(data *Tt) *Tt {
    data.Name = "ashan"
    data.Age = 32
    data.Email = "abc@abc.com"
    data.Addr = "china"
    data.Nickname = "ashan"
    return data
}

func Setint(data *int) *int {
    *data = 5 + 12*8
    return data
}

再次运行,耗时约为50.675µs。时间相差4到5倍之间。

这个例子告诉我们,函数调用传参的时候struct尽量要传递指针。原因很简单,如果不传递指针,在函数内部,会存在自己的作用域,由于域不同,则需要针对传递进来的类型,再次申请内存空间,创建一个值一样的副本,这个操作就相当耗时。

针对这个问题,只能重构修改,目前还没有进行,等待下一个版本优化重构时候在进行调整。

import cycle not allowed 问题

这个问题是在项目最后才出现的,当时非常奇怪,为什么会出现“循环引用”问题,最后发现是由于goalng的import包加载机制导致的。

简单解释一下可以立即为,在包A中 import 包B,而包B中 import 包A。当进行编译时,则发生互相递归引用,从而发生问题。

思考良久,如此问题怎样解决会比较好,产生这个问题的原因可能会出现在一下两种情况中:

  1. 使用的库存在互相应用的问题
  2. 自身模块结构设计存在问题

第一种问题基本属于掉坑了,解决的方法没啥好办法,只能自己想办法调整。

第二种情况可以使用重构来解决,这也是我未来要做的事情。出现这种情况,只能将功能重复的代码作为公用库放到一个独立的包当中,从而避免此类问题发生。

大写与小写

golang算是在语法糖中把“吝啬”做到了机智,在函数对外访问权限设计中,连public 这样的关键词都不提供,直接使用首字母大小写来区分。

一开始我设想所有 private 访问权限函数全部使用 _ 开头。看了一下golang中源码的一些实现方式,并没有这种习惯。索性就不采用这种方式。但很多时候这种规则容易忘记,尤其是我一开始直接使用 Sublime 编写代码时候,由于安装任何插件,没有代码提示,经常大小写搞混。

对于函数调用的问题还好,毕竟编译时候会提示你调用的函数不存在。但将 struct 转为字符串 和借助 mgo 查询数据时,会得到空的结果,极其令人头疼。与此同时,struct 作为数据库查询结果返回的时候,字段名称对应的首字母也要大写,和数据库中字段大小写不一致,这也是个不大不小的问题。

内存

老生常谈的问题又来了,这20天对于golang的接触与使用,并没有太多关注内存的控制,顶多是对变量的开辟小心处理而已,但我相信依然存在不少内存方面的隐患,待仔细研究后再来总结分享。

总结

总体来说,我对golang的使用体验还算满意,用起来像C。开发思路上没遇到大的问题,后续慢慢深入。

enjoy!


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4135 次点击  
加入收藏 微博
1 回复  |  直到 2017-11-27 02:36:04
Elemyin
Elemyin · #1 · 7年之前

新手,讲的都遇到过。

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传