GO windows安装

软件下载

 
https://golang.google.cn/
https://dl.google.com/go/go1.20.5.windows-amd64.msi


环境变量配置

 
我的电脑--属性--环境变量-用户环境变量 添加一下

GOWKS=G:\tpf\gowks
GOROOT=%GOWKS%\app\gowin
GOBIN=%GOWKS%\bin
GOPATH=%GOWKS%

将下面的路径添加到path中
%GOROOT%\bin
%GOBIN%

GO linux安装

软件下载

 
https://dl.google.com/go/go1.19.3.linux-amd64.tar.gz
https://studygolang.com/dl/golang/go1.18.10.linux-amd64.tar.gz
https://golang.google.cn/

Go环境变量设置

 
export GOWKS=/opt/wks/gowks
export GOROOT=$GOWKS/app/go
export GOBIN=$GOWKS/bin
export GOPATH=$GOWKS
export PATH=$GOROOT/bin:$GOBIN:$PATH

GOWKS是自定义的GO工作空间,
GO软件安装在其app/go目录下,
GOWKS同时也是GOPATH,
这里面包含项目运行的GO软件,下载的依赖包,编辑后的命令,说明文档等一切项目相关的文件。

后续若进行项目迁移,不管是GO本身版本变化,还是它的依赖包版本变化,
直接将这个目录COPY走就解决了所有问题。

GO ENV
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct  # 国内七牛云提供

GO mod vendor使用

go mod

 
mkdir esql
cd esql 
go mod init 
就完成go mod的初始化化了

go mod tidy 
这一步自动将go文件引入的外部包写入mod文件,并修改sum文件

如果要使用或找不到本地包,则修改mod相应的包指向本地目录位置
require gitee.com/ol v0.0.0-00010101000000-000000000000 // indirect
replace gitee.com/ol => ../../ol

go vendor

 
进入包目录,执行
go mod vendor 
就可以将依赖的外部包打包一份到vendor目录下,repalce指向本地的除外

这里要求你的项目放在GOPATH/src目录下
依赖于GOPATH,可放于GOPATH/src目录下,或者GOPATH/src的项目目录下
查找顺序:从当前模块目录找vendor目录,一直找到GOPATH/src
使用:手动依赖包或自己写的模块放到vendor目录,或者mod模式下进入目录执行go mod vendor
好处:下载的依赖包随项目走,不用关心这些依赖包的版本变化导致项目不可用了

注意事项
go vendor是要放在gopath/src目录下的
如果gopath/src/vendor与gopath/src下存在相同的模块,则vendor目录的优先级高,
即会调用vendor下的模块
而go mod的模块目录如果使用replace指定特定目录后,就不会走vendor了
如果使用go mod编辑报错同时又是个人项目,可以关闭go mod:go env -w GO111MODULE=off
没了go mod的自动下载,就将手工将下载的依赖包放到vendor下,
项目迁移时,vendor随之迁移,这样的项目也是极其稳定的,
或者像文章开始那样搭建项目,项目相关所有文件都放在$GOWKS目录下,
迁移时,GO版本与其依赖包都不变化,这样就万无一失了。

如果没有使用go mod,那么下载并编辑项目github.com/kardianos/govendor,生成一个govendor
go get -u -v github.com/kardianos/govendor
go mod init
go mod tidy
go build

govendor用法
govendor init
初始化vendor目录

govendor add +external
添加外部依赖

govendor update +external
更新外部依赖

govendor update $PACKAGE_NAME
更新指定包的依赖

go环境变量配置2
 
export GOWKS=/opt/tpf/liu
export GOROOT=$GOWKS/app/go
export GOBIN=$GOWKS/bin
export GOPATH=$GOWKS
export PATH=$GOROOT/bin:$GOBIN:$PATH
go env
 
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct  # 国内七牛云提供
GO 变量定义

GO有四种数据类型,数字、布尔、字符、派生类型;这里使用 前三种 简单类型 来说明变量的定义与使用

 
int8/uint8 
int16/uint16 
int32/uint32 
int64/uint64 
float32
float64 
complex64
bool 
byte 
rune :32位有符号整型,存储Unicode字符
int/uint :是32位还是64位看平台,其他的通过名字就能看到多少位

uint8 0-255,int8则是-128-127,这两个是Go的最小长度类型,其他类型在内存中分配的长度都要比这两个大;

-------------------------------------------- 
package main

import "fmt"
var (   
    aa = 1   
    bb = true   
    ss = "作用域为包的变量"   
    s2,s3 = "包变量的位置可能写在包内的任何地方","即可以是引用的前面也可以在引用的后面"
)
//GO有四种类型,数字、布尔、字符、派生类型
//变量的默认值
func var1(){
    var a int
    var b bool
    var f float64
    var s string
    // %d 表示数字,%s表示字符串,%q可以为字符串带上双引号
    fmt.Printf("%d-%s-%q\n",a,s,s)  // 0--""
    fmt.Println(b)  //false
    fmt.Println(f)  //0
}

//变量初始化
func var2(){
    var a int = 100  //明确地写出了变量的类型
    var b,f,s = true,3.14,"批评别人时,一定要顾及听者的面子" //不定义类型,同时多变量写于一行
    fmt.Println(a,b,f,s)
    var aa = 300
    var ss = "在回答别人或对别人发表观点时,一定要先准确理解别人的意思"
    fmt.Println(aa,ss)
}

//较常用的变量声明赋值方式
func var3(){
    //多行合并为一行,省去了类型,连var关键字也省去了,编辑器自动判断变量类型;只能用于一次声明变量时使用
    s1,s2 := "话越多","越没有份量"
    fmt.Println(s1,s2)
    //第二次使用时,不可再加冒号
    s1,s2 = "讲话时不能只顾着自己说","更要注意对方的感受和情绪变化"
    fmt.Printf("%s,%q",s1,s2) //讲话时不能只顾着自己说,"更要注意对方的感受和情绪变化"
}

func main() {
    var1()
    var2()
    var3()
}
go build

 
root@kl:/opt/wks/gowks/src/cmd# dcService -c /etc/dc.cnf
dcService: /usr/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by dcService)
dcService: /usr/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by dcService)

# ldd --version
ldd (Ubuntu GLIBC 2.31-0ubuntu9.7) 2.31

# gcc -dumpversion
9

当初build时的glibc版本高于现在运行的

所以,build的glibc版本不要太高,不要高于使用者的glibc版本

 

    

 

    

 

    

 


 

  

 


变量几个注意事项

变量的命名:
推荐使用studentName,而不是student_name
首字母大写有特殊的含义,比如一个包的方法要想在其他包中使用,那么该方法名称必须首字母大写,又比如结构体中的属性等

变量的作用域:
比如包a下有b.go与c.go,b.go中有方法C,则其他包引用的方式为a.C()
包,即文件所在目录的名称,包名文件夹下可以有多个文件,包内变量的作用域是可以跨越这些文件的;
比如,一个包中不允许存在两个相同名称的方法,会提示重复;
函数内的变量的作用域就只是在函数内了

字符串
字符串分为原生字符串、解释型字符串两种;
原生字符串使用``(反引号),解释型字符串使用双引号"",解释型字符串中可以解析转义字符;

GO 常量与枚举

 
package main

import (
    "fmt"
    "math"
)

//常量
func cons(){
    const a,b= 3,4  //常量的数字在不明确指定类型的情况下,即可以作为int使用,也可以作为float32/float64使用
    var c int
    c = int(math.Sqrt(a*a+b*b)) //不需要转float64
    fmt.Println(c)         //5
    const aa,bb int = 3,4
    cc := math.Sqrt(float64(aa*aa + bb*bb))
    fmt.Println(cc)        //5
    fmt.Println(s1,s2)     //你多少次在讲话前 没有去在意对方的心思
}

//包内常量,go的常量通常不全部大写表示,这是因为go语言定义的变量或常量,首字母大写是有特定含义的
const (
    s1,s2 ="你多少次在讲话前","没有去在意对方的心思"
)

//枚举
func enum(){
    //在go中可以简单地使用const常量来表示枚举
    const(
        java = 0
        net = 1
        c =2
        rust = 3
    )
    const(
        aa = iota //一个行计数器,从0开始,刚好与枚举从零开始相符,故而使用iota简化枚举的写法
        bb
        _  //_一个占位符,这样下面的dd才能被赋值3
        dd
    )
    const(
        byte = 1 <<(10 * iota)
        kb
        mb
        gb
        tb
        pb
    )
    fmt.Println(byte,kb,mb,gb,tb,pb)  //1 1024 1048576 1073741824 1099511627776 1125899906842624
}

func main() {
    cons()
    enum()
}
GO 数组与切片

数组

 
var arr1 = [4]uint8{192,168,0,1}
var arr2 = [...]uint8{192,168,0,2}

...,三个小黑点,由Go编译器计算该值的元素数量并以此获得其长度,也适用于函数参数

切片

 
var slic1= []string{"192.168.0.1","192.168.0.2"}
var slic2=append(slic1,"192.168.0.3")
var slic3=make([]string,50)

append可以为切片类型[]string追加元素

make可以高效地为一个切片初始化数据,make([]string,50)则是一次性初始化50个默认值为""的元素

len与cap

 
func main(){
    println(len(arr1),cap(arr2),len(slic2),cap(slic3))
}

输出
4 4 3 50

go map

 
package main
var m1 = map[string]bool{}

func main(){
    m1["魔镜,我是世界上最美的女人吗"]= false
    println(m1["魔镜,我是世界上最美的女人吗"])
    println(len(m1))
    delete(m1,"魔镜,我是世界上最美的女人吗")
    println(len(m1))
    delete(m1,"魔镜,我是世界上最美的女人吗")
    println(len(m1))
}

delete可以删除本身就不存在的元素,输出
false
1
0
0

相比数组的定义,
map多了关键字map,
以及key的类型,放在了中括号里 
map[key type]value type{}

GO 流程控制

for循环

 
for i:= 0;i<9;i++ {
    fmt.Println(i)
}

for循环数组

 
for index, val := range arr{
    fmt.Printf("第 %d 位 x 的值 = %d\n", index, val)
}
    

for循环map

 
for key, value := range oldMap {
    newMap[key] = value
}

for 永远循环,死循环中通常会有跳出循环的条件

 
for {
    record, err := r.Read()
    
    if err == io.EOF {
        break
    }
    if err != nil {
        log.Fatal(err)
    }
    for i:= 0;i<r.FieldsPerRecord;i++ {
        fmt.Println(i,record[i])
    }
}

if 条件语句

 
package main

import (
    "fmt"
    "io/ioutil"
)
func if1(){
    const filename = "/tmp/a.log"
    if txt, err := ioutil.ReadFile(filename); err != nil {
        fmt.Println(err)
    } else {
        fmt.Printf("%s\n", txt)
    }
}

go switch: 找到第1个条件成立的分支就返回

 
package main

import (
    "fmt"
)

func switch1(level int) string{
    res := ""

    switch level{
    case 1:
        res = "100000"
    case 2:
        res = "30000"
    case 3:
        res = "10000"
    default:
        res = "1000"
    }
    return res
}
func switch2(level int) string{
    res := ""

    switch {
    case level == 100:
        res = "100000"
    case level > 90:
        res = "30000"
    case level > 80:
        res = "10000"
    case level > 60:
        res = "1000"
    case level <= 60:
        panic("You ......")
    }
    return res
}

func main() {
    res := switch1(1)  
    println(res) //100000

    fmt.Println(switch1(1),switch1(2))  // 100000 30000

    fmt.Println(switch2(100),switch2(88)) // 100000 10000

  //下面这个是直接报错,并不会输出前两个到第三个时再报错
  fmt.Println(switch2(100),switch2(88),switch2(38))
}

GO 结构体

结构体定义示例

 
变量  : var   name 数据类型 
常量  : const name 数据类型 
结构体: type   name 数据类型 --> type Student struct 

从上面三行感受一下GO语言变量设计的风格:
第一个关键词 表示要定义的事物属于哪个大类,是变量,还是常量,还是本身就是一个类型 
第二个关键词 表示要定义的事物的名称 
第三个关键词 表示细分的数据类型,是简单类型数字,还是复合类型 字符串,结构体等  

package main 
import (
	"fmt"
)

type Student struct {
    id int 
    name string
}

func (st *Student) ShowName(){
	st.name = "花开12瓣,瓣瓣为一生"
	fmt.Println(st.name)
}

func main(){
	s1 := Student{}
	s1.ShowName()
}

go fmt及数字转化

常用格式化输出

 
package main 
import (
    "fmt"
)
func main(){
    fmt.Println("我来人间一趟")
    fmt.Printf("%s\n","本来无念无想")
    ss := fmt.Sprintf("%v","一入红尘就变了模样")
    println(ss)
}

%d 表示十进制
%e 科学计数法,例如 -1.4e+11
%f 小数点
%o 表示八进制
%s 字符串表示(string类型或[]byte)
%p 十六进制内存地址,前缀ox
%v 通用格式,按数据本身的类型输出,比如是字符串,此时%v自动转为%s的效果

package main 
import (
	"fmt"
)

type Student struct {
    id int 
    name string
}

func main(){
	s1 := Student{id:1,name:"韩立"}
	
	fmt.Printf("%v\n",s1)   // {1 韩立}
	fmt.Printf("%+v\n",s1)  // {id:1 name:韩立}
	fmt.Printf("%#v\n",s1)  // main.Student{id:1, name:"韩立"}
	fmt.Printf("%T\n",s1)   // main.Student
}

数字之间及字符串的转化

 
package main
import (
    "fmt"
    "reflect"
    "strconv"
)

func  main()  {
    //查看一个数据的类型
    fmt.Println(reflect.TypeOf("123"))  // string
    fmt.Println(reflect.TypeOf(1.23))   // float64

    strconv.Atoi("123") // 字符串转数字 
    strconv.Itoa(123)  // 数字转字符串

    strconv.FormatUint(uint64(123), 8) // 10进制转8进制
    strconv.FormatUint(uint64(123), 16)// 10进制转16进制

    strconv.FormatFloat(float64(1.23), 'e', 4, 32) //10进制转float32,保留4位有效数字,e表示科学计算法
    strconv.FormatFloat(1.23, 'f', 4, 64)          //10进制转float64,保留4位有效数字,f表示浮点数 
}

go连接oracle

依赖库

 
github.com/godror/godror
database/sql

客户端安装

 
oracle客户端,instantclient-basic-linux.x64-11.2.0.4.0.zip
rpm -qa | grep libaio
yum install libaio

动态库设置:
sudo sh -c "echo /opt/app/instantclient_11_2 > /etc/ld.so.conf.d/oracle-instantclient.conf"
sudo ldconfig
$ cat /etc/ld.so.conf.d/oracle-instantclient.conf
/opt/app/instantclient_11_2

参考文章
    
    oracle客户端下载-夸克网盘