javaer learn golang之基础

p_3er · · 1566 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

1、开始

我是一个javaer,最近空闲时间在学习golang。

度娘后,安装好Go环境和LiteIDE后,一开始我也没从基础开始看,而是想把现有的java项目改成是golang版本的。

原项目内容:

  1. socket模块接收下位机的数据
  2. 对协议数据进行解析
  3. 把协议数据解析后存进数据库
  4. web子项目

golang相比java,有很多很方便的特性。特别是并发与网络方面更是golang的卖点。所以我就直接找了个socket的例子开始模拟着实现项目的socket模块

2、第一个程序

server.go :

package socket

import (
    "fmt"
    "net"
    "strings"
)

func  StartServer() {
    service := ":3338"
    tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
    checkError(err)
    listener, err := net.ListenTCP("tcp", tcpAddr)
    checkError(err)
    for {
        conn, err := listener.Accept()
        if err != nil {
            continue
        }
        fmt.Println("新连接:", conn.RemoteAddr().String())
        go handleConn(conn)
    }
}

func handleConn(conn net.Conn) {
    for {
        buffer := make([]byte, 1024)

        length, err := conn.Read(buffer)
        if err != nil {
            conn.Close()
        }

        if length > 12 {
            data := buffer[:length]

            switch data[11] & 0xff {
            case 0x80:
                //桌子
                fmt.Println("桌子")
            case 0x90:
                //椅子


            case 0xA0:
                //台灯

            default:
                //其它

            }

            //写数据

            //      conn.Write(data)
        }
    }

}

func isProtocol(data []byte) bool {
    if (data[0]&0xff) == 0xC0 && (data[len(data)-1]&0xff) == 0xC1 {
        return true
    }
    return false
}

func checkError(err error) {
    if err != nil {
        fmt.Println(err.Error())
    }
}

因为是第一篇笔记,也简单地说一下golang的基础语法。

对于一个javaer来说,或者一个有计算机语言基础的朋友来说,golang的语法看起来不会太困难。

3、包路径

像java一样,一开始我们为程序声明一个包路径

package socket

和java不一样的是,golang的包不是层叠式的。所以为了方便识别我们也可以为我们所有的项目放到一个父包下。

类似与java,我这里使用了一个letus.xyz的命名作为父包(文件夹)。这样其它的程序就能比较方便地找到server.go程序来调用。

这里写图片描述

如果想要构建一个程序,则包和包内的文件都必须以正确的顺序进行编译。包的依赖关系决定了其构建顺序。

属于同一个包的源文件必须全部被一起编译,一个包即是编译时的一个单元,因此根据惯例,每个目录都只包含一个包。

如果对一个包进行更改或重新编译,所有引用了这个包的客户端程序都必须全部重新编译。

4、包与库的导入

import (
    "fmt"
    "net"
    "strings"
)

和java相比,golang使用的这种方式进行导包和库看起来优雅多了。

当然,你也可以像java一样,一个一个地import

import "fmt"    
import  "net"
import  "strings"

注意事项:

如果你导入了一个包却没有使用它,则会在构建程序时引发错误,如 imported and not used: os,这正是遵循了 Go 的格言:“没有不必要的代码!“。

当你导入多个包时,导入的顺序会按照字母排序。

如果包名不是以 . 或 / 开头,如 “fmt” 或者 “container/list”,则 Go 会在全局文件进行查找;如果包名以 ./ 开头,则 Go 会在相对目录中查找;如果包名以 / 开头(在 Windows 下也可以这样使用),则会在系统的绝对路径中查找。

导入包即等同于包含了这个包的所有的代码对象。

除了符号 _,包中所有代码对象的标识符必须是唯一的,以避免名称冲突。但是相同的标识符可以在不同的包中使用,因为可以使用包名来区分它们。

5、 函数

导入包和库之后,就是我们的程序主体了。当然,我们写程序的时候肯定是package之后就直接写程序主体,而包与库是到用到这个包内容的时候再导。

golang和c一样,是面向过程的函数式编程,而不是java那样的面向对象。

func  StartServer() {

}

func isProtocol(data []byte) bool {

    return false
}

func checkError(err error) {

}

可见性规则:

当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 private )。

函数的基本结构:

func functionName(parameter_list) (return_value_list) {
   …
}

其中:

  • 参数:parameter_list 的形式为 (param1 type1, param2 type2, …)
  • 返回类型return_value_list 的形式为 (ret1 type1, ret2 type2, …)

golang的方法比java有意思的是它允许返回多个值。而它的参数表示形式与java也不一样,名字是放在类型的前面。

6、变量

service := ":3338"

:=是简短声明语法 ,表示声明并赋值。
或者你也可以用var来声明:

var service = ":3338"

var service string
service = ":3338"

简短声明法看起来更加优雅些。

7、常量

const (
    Unknown = 0
    Female = 1
    Male = 2
)

我们第一个程序没用到常量。常量是通过const来定义的。

常量的定义格式:

const identifier [type] = value

8、基本数据类型

  • int,Runes(注:Rune 是int 的别名)
  • int8 ,int16 ,int32 ,int64
  • byte ,uint8 ,uint16 ,uint32 ,uint64 (注:byte是uint8 的别名)
  • float32 ,float64 (没有float 类型)
  • bool
  • string
  • complex128,complex64

9、main函数

package main

import (
    "letus.xyz/socket"
)

func main() {
    socket.StartServer()
}

这里我们通过绝对路径letus.xyz主包找到socket包来调用程序。当然我们也可以相对目录导入。很明显,相对路径的方式不利于包的复用。

所以个人建议使用绝对路径来导包,毕竟思想上和java相似。

import (
    "../socket"
)

10、其它

golang的运算符与控制结构语句的使用基本和java的一样,但值得一提的是,golang的switch语法支持字符串的匹配。这是作为一个javaer经常想java也提供的一个特性。

switch field.Type().String() {
case "time.Time":
    v, _ := time.Parse("2006-01-02 15:04:05", s)
    field.Set(reflect.ValueOf(v))
}

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

本文来自:CSDN博客

感谢作者:p_3er

查看原文:javaer learn golang之基础

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

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