最全的Go开发教程,超详细哦

一、Go简介

Go是2009年开源的编程语言,Go语言具有以下特性:语法简洁、并发编程、编译迅速、数组安全、丰富的内置类型、错误处理、匿名函数和闭包、反射、函数多返回值、自动垃圾回收。

二、Go语言安装与配置

Go语言支持以下系统:Linux、Mac、Windows。

安装包下载地址:https://golang.org/dl/

如果打不开可以使用这个地址:https://golang.google.cn/dl/

在这里插入图片描述

下面介绍Windows和Linux系统的安装:

1、Windows系统下安装:

可以直接点击.msi进行下载,比如上述图片的go1.19.1.windows-amd64.msi,下载完后打开msi,进行安装,安装目录可以使用默认,也可以自己配置,安装目录不可以有中文。然后配置系统环境变量:添加GOROOT,值为Go的安装目录,例如D:\Program Files\Go。然后可以在cmd里执行go version,如果出现类似输出:go version go1.19.1 windows/amd64,说明安装配置成功,接下来就可以进行开发运行go程序了。

2、Linux系统下的安装:

1)下载二进制包:go1.19.1.linux-amd64.tar.gz

2)将下载的二进制包解压至/usr/local目录

tar -C /usr/local -xzf go1.19.1.linux-amd64.tar.gz

3)将 /usr/local/go/bin 目录添加至 PATH 环境变量:

export PATH=$PATH:/usr/local/go/bin

以上只能暂时添加 PATH,关闭终端然后下次再登录又没有了。
可以编辑 ~/.bash_profile 或者 /etc/profile,并将以下命令添加该文件的末尾,这样就可以永久生效:

export PATH=$PATH:/usr/local/go/bin

添加后需要执行:

source ~/.bash_profile
或者
source /etc/profile

三、Go语言开发结构与流程

以下程序是在windows系统的VS Code编辑器开发的,安装Go扩展可以方便开发。
Go语言程序的基本结构有以下几个组成:包声明、引入包、函数、变量、语句、表达式、注释。
以下是一个输出Hello, World!的main.go程序:

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

打开命令行,在保存程序文件的目录中执行go run main.go,输出Hello, World!。

可以使用go build命令来生成二进制文件:

go build main.go

四、Go语言的基础定义

1、标识符:

Go语言标识符与其它语言类似,第一个字符必须是字母、下划线,不能是数字。

2、关键字

Go语言的25个关键字或者保留字:
var, type, switch, struct, select, return, range, package, map, interface, if, import, goto, go, func, for, fallthrough, else, default, defer, const, case, continue, chan, break.
Go语言的36个预定义标识符:
append, bool, byte, cap, close, complex, complex64, complex128, uint16, copy, false, float32, float64, imag, int, int8, int16, uint32, int32, int64, iota, len, make, new, nil, panic, uint64, print, println, real, recover, string, true, uint, uint8, uintptr.

3、注释:

// 单行注释
/*
 xxxxx
 多行注释
 */

五、Go语言的数据类型

有如下类型:
1、数字类型
整型 int 和浮点型 float32、float64,Go 语言支持整型、浮点型数字和支持复数。
2、布尔类型
布尔型的值只可以是常量 true 或者 false。例子:var b bool = true。
3、字符串类型:
字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的。Go语言的字符串的字节使用UTF-8编码标识Unicode文本。

六、Go语言变量与常量

1、声明变量与变量赋值

// 声明变量的一般形式是使用 var 关键字:
var variable type
// 也可以一次声明多个变量:
var variable1, variable2 type
// 声明变量时也可以赋值
var temp string = "ssss"
var a, b int = 1, 2

声明了变量并且赋值了,也可以不用写类型。

如果声明了变量没有赋值,那么变量的值为零值。比如var a bool的零值为false。

下面是一些类型数据的零值:

  • 数值类型(包括complex64/128)为0
  • 布尔类型为 false
  • 字符串为 “”
  • 以下几种类型零值为nil:
    var a *int
    var a []int
    var a map[string] int
    var a chan int
    var a func(string) int
    var a error // error 是接口

声明变量更加简洁的方式:

a := 1

相当于:

var a int 
a = 1 

声明全局变量和函数变量:

ackage main

var (  // 这种因式分解关键字的写法一般用于声明全局变量
    a int
    b bool
)

// 这种不带声明格式的只能在函数体中出现
// c, d := 3123, "hello"

func main(){
    c, d := 3123, "hello"
}

2、常量

常量是在程序运行时不会被修改的量。常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

常量的定义格式如下:

const variable [type] = value
你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型
    const a string = "abc"
    const a = "abc"
多个相同类型的声明可以简写为:
const c1, c2 = value1, value2

常量可以用len()等内置函数计算表达式的值,在常量表达式中,函数必须是内置函数,否则编译不通过

ackage main

const (
    a = "abc"
    b = len(a)
)

func main(){
    println(a, b)
}

iota是一种特殊常量,可以认为是一个可以被编译器修改的常量。iota在const关键字出现时将被重置为0,const中每新增一行常量声明,iota计数一次。

package main

import "fmt"

func main() {
    const (
        a = iota   //0
        b          //1
        c          //2
        d = "hh"   //独立值,iota += 1
        e          //"ha"   iota += 1
        f = 312    //iota +=1
        g          //312  iota +=1
        h = iota   //7,恢复计数
        i          //8
    )
    fmt.Println(a,b,c,d,e,f,g,h,i) // => 0 1 2 hh hh 312 312 7 8
}

3、变量作用域

作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。

Go语言中变量可以在三个地方声明:

  • 函数内定义的变量(局部变量):作用域只在函数体内,参数和返回值变量也是局部变量。
  • 函数外定义的变量(全局变量):在函数体外声明的变量称之为全局变量,全局变量可以在整个包甚至外部包(被导出后)使用。
  • 函数的形式参数:形式参数可以看作函数的局部变量。

七、Go语言运算符

Go语言运算符与java等语言基本一样,均有:算术运算符、关系运算符、逻辑运算符、赋值运算符、位运算符。
比较例外的是,Go语言有与C/C++类似的指针相关运算符:

运算符描述示例
*指针变量*a是一个指针变量
&返回变量存储地址&a: 变量的存储地址
package main

import "fmt"

func main() {
   var a int = 22
   var ptr *int

   // ptr变量存储了a的地址
   ptr = &a
   fmt.Printf("a的值为 %d\n", a);
   fmt.Printf("ptr的值为 %s\n", ptr);
   fmt.Printf("*ptr的值为 %d\n", *ptr);
}

输出:

a的值为 22
ptr的值为 %!s(*int=0xc00000e0a8)
*ptr的值为 22

八、Go语言函数

Go语言程序至少有一个main函数。

1、函数定义

func function_name( [parameter list] ) [return_types] {
   // 函数体
}

2、函数使用

以下代码定义了函数和函数调用:

package main

import "fmt"

func main() {
   var a int
   a = sum(1, 2)
   fmt.Printf("a的值为 %d\n", a);
}

func sum(a, b int) int {
	var c int
	c = a + b
	return c
}

返回多个值的函数:

package main

import "fmt"

func swap(x, y string) (string, string) {
   return y, x
}

func main() {
   a, b := swap("cc", "dd")
   fmt.Println(a, b) // 输出:dd cc
}

九、Go语言条件语句

Go语言条件语句的执行逻辑与其它语言是一致的(但是Go语言多了个select语句),主要是写法不同

1、if语句

定义:

if 布尔表达式 {
   /* 在布尔表达式为 true 时执行 */
}

示例:

package main

import "fmt"

func main() {
   var a int = 1
   if a < 10 {
       // 如果条件为true时执行以下语句
       fmt.Printf("a小于10\n" )
   }
}

if else 语句:

if 布尔表达式 {
   /* 在布尔表达式为 true 时执行 */
} else {
  /* 在布尔表达式为 false 时执行 */
}

2、switch语句

定义:

switch temp {
    case temp1:
        // 
    case temp2:
        //
    default:
        //
}
或者
switch {
    case 布尔表达式1:
        // 
    case 布尔表达式2:
        //
    default:
        //
}

示例:

package main

import "fmt"

func main() {
   var a string = ""
   var num int = 10

   switch num {
      case 123: a = "大于10"
      case 10: a = "等于10"
      case 1, 2: a = "小于10"
      default: a = "不知道"
   }

   switch {
      case a == "等于10":
         fmt.Printf("a等于10!\n" )    
      case a == "大于10", a == "小于10":
         fmt.Printf("a大于或者小于10!\n" )      
      default:
         fmt.Printf("其它情况\n" );
   }

   fmt.Printf("num的值为: %d, a的值为: %s", num, a );
}

输出:

a等于10!
num的值为: 10, a的值为: 等于10

fallthrough

使用fallthrough会强制执行后面的case语句,使用fallthrough时不会判断下一条 case 的表达式结果是否为 true,直接执行。

package main

import "fmt"

func main() {

    switch {
    case false:
            fmt.Println("1、case条件为false")
            fallthrough
    case true:
            fmt.Println("2、case条件为true")
            fallthrough
    case false:
            fmt.Println("3、case条件为false")
            fallthrough
    default:
            fmt.Println("默认case")
    }
}

输出:

2、case条件为true
3、case条件为false
默认case

3、select语句

select语句随机执行一个可运行的case,如果没有可运行的case,将阻塞运行,直到有 case 可运行,
每个case都必须是一个通信

定义:

select {
    case a: // 通信a
       // 
    case b: // 通信b
       //
    default:
       //
}

十、Go语言循环语句

Go语言循环的语法有点差别,for循环的写法也有差异,没有while循环。
示例:

// 循环遍历
for i := 0; i < count; i++ {
    //
}

// 类似map遍历
for _, v := range map {
    // 
}

// 
for 布尔表达式 {
    // 
}
示例:
for 1 > 0 {
    fmt.Printf("111")
}

go循环程序中可以用break、continue、goto语句控制循环执行过程。

十一、Go语言数组

Go语言数组是具有相同唯一类型的一组长度固定的数据结构,这种类型可以是任意的原始类型例如整型、字符串,也可以是自定义类型。可以通过索引来读取或者修改数组元素。

1、一维数组

1)、数组声明:

var arr_name [size] type

例如:

var arr [3] int

2)、初始化数组

var arr = [2]float32{2.1, 3.3}

或者

arr := [2]float32{2.1, 3.3}

如果数组长度不确定,可以使用…代替数组的长度,编译器会根据元素个数自行推断数组的长度:

var arr = [...]float32{2.1, 3.3}
或者
arr := [...]float32{2.1, 3.3}

如果设置了数组的长度,还可以通过指定数组下标来初始化元素或者修改元素值:

arr := [2]float32{2.1, 3.3}
arr[1] = 1.1

2、多维数组

1)数组声明

var arr [size1][size2]...[size_n] type

例如三维数组:

var arr [4][22][3] int

下面以二维数组举例:

二维数组本质上是由一维数组组成的。

arr := [][]int{}

// 可以使用append()函数向空的二维数组添加两行一维数组
row1 := []int{1, 2, 3}
row2 := []int{4, 5, 6}
arr = append(arr, row1)
arr = append(arr, row2)

fmt.Println("arr为:", arr)
fmt.Println("第一个元素为:%d", arr[0][0])

也可以这样初始化二维数组:

arr := [2][4]int{
 {0, 1, 2, 3} ,
 {4, 5, 6, 7} , // ,不能省略
}

二维数组取值赋值:

赋值:
arr[2][1] = 222
取值:
a := arr[2][1]

3、数组作为函数参数:

void fun(param [3]int)
{
    //
}
或者不指定数组长度
void fun(param []int)
{
    //
}

十二、Go语言结构体

结构体是由相同类型或不同类型的数据组成的数据集合。

1、定义与使用

type struct_name struct {
   filed1 type
   filed2 type
   filed3 type
}

示例:

package main

import "fmt"

type Book struct {
   name string
   author string
}

func main() {
    stru := Book{"编程设计", "xian"}
    fmt.Println("stru为:", stru)

    var book1 Book
    book1.name = "js程序设计"
    book1.author = "xxx"
    fmt.Println("book1: ", book1)

    // 也可以使用key => value格式
    fmt.Println(Book{name: "编程设计", author: "xian"})
}

输出:

stru为: {编程设计 xian}
book1:  {js程序设计 xxx}
{编程设计 xian}

访问结构体成员:

结构体.成员名

2、结构体作为参数传递:

package main

import "fmt"

type Book struct {
   name string
   author string
}

func main() {
    stru := Book{"编程设计", "xian"}
    fmt.Println("stru为:", stru)

    getInfo(stru)
}

func getInfo( book Book ) {
    fmt.Println( "Book name为: ", book.name)
}

输出:

stru为: {编程设计 xian}
Book name为:  编程设计

3、结构体指针

可以定义指向结构体的指针:

var struct_pointer *结构体名称 // 注意不是结构体变量名称

获取结构体变量地址:

struct_pointer = &str

使用指针访问结构体成员:

struct_pointer.name

十三、Go语言集合(Map)

Map是一种无序的键值对的集合。

1、定义map

// 声明变量,默认map是nil
var map_variable map[key_type]value_type

// 或者使用make函数
map_variable := make(map[key_type]value_type)

示例:

package main

import "fmt"

func main() {
    var capitalMap map[string]string
    capitalMap = make(map[string]string)

    capitalMap["France"] = "巴黎"
    capitalMap["English"] = "伦敦"
    // capitalMap := map[string]string{"France": "巴黎", "English": "伦敦"}

    // 使用range遍历
    for k := range capitalMap {
        fmt.Println(k, " => ", capitalMap[k])
    }

    // 或者
    fmt.Println("\nk, v遍历: ")
    for k, v := range capitalMap {
        fmt.Println(k, " => ", v)
    }

    fmt.Println("\n")
    // 查看元素在集合中是否存在 */
    capital, ok := capitalMap["Itlay"]
    if (ok) {
        fmt.Println("Itlay的首都 ", capital)
    } else {
        fmt.Println("不存在Itlay的首都")
    }
}

delete删除:

delete(capitalMap, "France")

十四、Go语言range

for range循环可以对数组、字符串、slice、map等进行循环遍历。

1、遍历map

// 遍历map
for key, value := range map {
    map[key] = value
}

2、遍历数组

// 遍历数组
for i, val := range arr {
    // i代表索引,val代表相应的值
}

3、遍历字符串

// 遍历字符串。i是字符的索引,char是字符(Unicode的值)本身。
for i, char := range str {
    fmt.Println(i, char)
}

十五、Go语言切片

Go语言数组长度是固定的, 而切片提供了一种动态长度数组的功能。

1、创建切片与使用

可以使用make创建切片,len是数组的长度也是切片的初始长度。

var slice1 []type = make([]type, len)
或者
slice1 := make([]type, len)
// 也可以指定容量,capacity是可选参数
slice1 := make([]type, len, capacity)

切片初始化:

slice1 := []int{1,2,3 } 

截取:

s := arr[startIndex:endIndex] // 左闭右开
s := arr[:endIndex]
s := arr[startIndex:]

len()方法获取切片长度,cap()测量切片容量。

切片在未初始化之前默认为nil,长度为 0:

var slice1 []int
// slice1 == nil

2、append()函数:切片追加新元素:

package main

import "fmt"

func main() {
    var slice1 []int // 创建切片
    fmt.Printf("长度=%d, 容量=%d, 切片=%v\n", len(slice1), cap(slice1), slice1)

    // 向切片添加一个元素
    slice1 = append(slice1, 33)
    fmt.Printf("长度=%d, 容量=%d, 切片=%v\n", len(slice1), cap(slice1), slice1)
}

输出:

长度=0, 容量=0, 切片=[]
长度=1, 容量=1, 切片=[33]

3、copy: 拷贝切片

package main

import "fmt"

func main() {
    var slice1 []int // 创建切片
    slice2 := []int{32, 43} // 创建切片

    // 向切片添加一个元素
    slice1 = append(slice1, 33)

    // slice1拷贝到slice2
    copy(slice2, slice1)

    fmt.Printf("长度=%d, 容量=%d, 切片=%v\n", len(slice2), cap(slice2), slice2) // => 长度=2, 容量=2, 切片=[33 43]
}

十六、Go语言接口

// 定义接口
type interface_name interface {
    method_name1 [return_type]
    method_name2 [return_type]
    method_name3 [return_type]
    ...
    method_name_n [return_type]
}
 
// 定义结构体
type struct_name struct {
    variable1 type
    variable2 type
    ...
    variable_n type
}
 
// 实现接口方法
func (struct_variable_name struct_name) method_name1() [return_type] {
    /* 方法实现 */
}

示例:

package main

import (
    "fmt"
)

type Phone interface {
    speak()
}

type IPhone struct {
    name string
}

func (iPhone1 IPhone) speak() {
    fmt.Println("iPhone1 speak")
}

func main() {
    var phone Phone

    phone = new(IPhone)
    phone.speak()
}

十七、Go语言并发

Go语言并发:通过go关键字来开启goroutine。goroutine是轻量级线程,goroutine的调度由Golang运行时进行管理。go语句开启一个新的运行期线程,即就是goroutine,以一个不同的、新创建的goroutine来执行一个函数。同一个程序中的所有goroutine共享同一个地址空间。

1、goroutine 语法格式:

go 函数名(参数列表)

示例:

package main

import (
    "fmt"
    "time"
)

func printFun(s string) {
    for i := 0; i < 3; i++ {
        time.Sleep(200 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    go printFun("World")
    printFun("Hello")
}

2、使用通道(channel)传递数据

可以使用通道(channel)用来传递数据。通道可在两个goroutine之间通过传递一个指定类型的值来通讯。操作符<-指定通道的方向:发送或接收。如果没有指定方向,说明是双向通道。

创建通道:

chan1 := make(chan int)
chan1 <- val    // 把 val 发送到通道 chan1
temp := <-chan1  // 从 chan1 接收数据, 并且赋值给temp变量

示例:

package main

import "fmt"

func sum(nums []int, c chan int) {
    sum := 0
    for _, v := range nums {
            sum += v
    }
    // 把sum发送到通道c
    c <- sum 
}

func main() {
    a := []int{31 , 21, 3, 4}

    chan1 := make(chan int)
    go sum(a[:len(a)/2], chan1)
    go sum(a[len(a)/2:], chan1)
    sum1, sum2 := <-chan1, <-chan1 // 从通道c中接收两个sum结果

    fmt.Println(sum1, sum2, sum1 + sum2) // => 7 52 59
}
  • 8
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 致远OA是一款企业办公自动化软件,提供了众多的功能和工具,可以帮助企业高效地管理办公流程。为了满足企业特定的需求,致远OA允许二次开发,使得企业可以根据自己的需求进行定制化。 针对最新、最详细的致远OA二次开发教程,以下是一些建议: 1. 学习开发基础知识:在开始致远OA二次开发之前,建议先掌握一些基础的开发知识,比如数据库操作、编程语言、Web开发等。 2. 了解致远OA架构:在进行OA二次开发之前,最好先了解致远OA的整体架构和模块之间的关系,这样可以更好地理解自己的开发需求,并且快速定位到相应的模块。 3. 使用致远OA提供的二次开发工具:致远OA提供了一些二次开发工具,比如OA Studio、OA SDK等,这些工具能够帮助开发人员快速搭建和定制企业的OA系统。 4. 参考文档和教程:致远OA官方文档和教程提供了很多二次开发的指导和示例,可以作为学习和参考的资料。 5. 实践和练习:通过实践和练习,将所学的开发知识应用到具体的项目中,可以更好地掌握致远OA的二次开发技巧和方法。 总之,致远OA二次开发是一个相对复杂的过程,需要具备一定的开发知识和经验。通过学习基础知识、了解OA架构、使用开发工具、参考文档和教程以及实践练习,可以帮助开发人员更好地进行二次开发,并根据企业的需求进行定制化。 ### 回答2: 致远OA是一款常用的办公自动化软件,通过二次开发可以为企业定制化开发各种功能。下面是关于致远OA二次开发教程的最新最详细信息(截至2021年): 1. 学习基础知识:致远OA二次开发基于Java语言开发,因此需要熟悉Java语言的基本语法和开发框架,如Spring、MyBatis等。同时也需要了解数据库相关知识,如MySQL、Oracle等。 2. 获取开发文档:致远OA官方提供了详细开发文档,包含API接口、数据表结构等内容。开发者可以根据文档来了解软件的内部机制和可操作的对象。 3. 配置开发环境:搭建开发环境是二次开发的前提。需要安装Java开发工具包(JDK)、开发工具(如Eclipse、IntelliJ IDEA)以及相应的数据库。 4. 分析需求:在进行二次开发之前,需要与企业相关部门沟通,了解他们的具体需求。根据需求分析,确定开发方向和功能点。 5. 编写代码:根据需求进行具体的开发工作。可以使用Java语言、多种开发框架来实现功能。其中,涉及到数据库的操作可以通过MyBatis等框架来简化。 6. 调试测试:开发完成后,需要进行调试和测试。在本地环境中测试功能的正确性和稳定性,确保没有漏洞和错误。 7. 部署上线:当功能测试通过后,将代码部署到生产环境中并进行上线。在上线之前,需要备份数据,确保数据的安全性。 8. 维护和优化:二次开发上线后,可能会出现一些问题或用户的反馈。需要及时进行维护和优化,改进用户体验。 总之,致远OA二次开发需要具备Java编程和数据库知识,并按照需求进行开发、测试和部署。通过持续的维护和优化,可以为企业提供更好的办公自动化解决方案。 ### 回答3: 《致远OA二次开发教程-最新最详细2021》是一本指导人们如何进行致远OA系统二次开发教程。致远OA是一套企业管理软件,能够帮助企业实现办公自动化和企业资源规划,为企业提供高效的管理方式。 这本教程以最新的版本为基础,详细介绍了致远OA系统的二次开发过程。首先,它会向读者介绍致远OA系统的基本架构,包括前端和后端的技术栈,以及常用的开发工具和软件。 教程的下一部分会教授读者如何使用致远OA系统的开发接口,包括API和插件机制。读者将学习如何通过API与致远OA系统进行数据交互,以及如何使用插件机制扩展系统的功能。这些知识将帮助开发者根据自己的需求进行个性化的定制和开发教程还将介绍一些常用的二次开发技巧和方法,如如何修改致远OA系统的界面样式、如何添加新的功能模块、如何优化系统的性能等。通过这些技巧和方法,开发者可以更好地满足企业的需求,并提高系统的稳定性和用户体验。 此外,教程还提供了大量的实例和案例,帮助读者更好地理解和应用所学知识。这些实例涵盖了各种不同的开发场景,从简单的功能扩展到复杂的系统集成,读者可以根据自己的实际情况选择合适的实例进行学习。 总之,《致远OA二次开发教程-最新最详细2021》是一本帮助开发者学习如何进行致远OA系统二次开发的权威指南。无论是初学者还是有一定经验的开发者,都可以从中获得宝贵的知识和经验,提高自己的开发水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值