1、Golang基础--Go简介、环境搭建、变量、常量与iota、函数与函数高级
阅读原文时间:2023年07月08日阅读:1

1 Go语言介绍

1 golang--》Go---》谷歌公司 2009年
    golang:指go语言,指的go的sdk
    goland:软件,ide:集成开发环境  Java写的
2 Go是静态强类型语言
    静态:需要编译再执行
            C、C#、Java:编译成不同平台的可执行文件在不同平台执行
            c语言:编译慢
            Go:编译快、并且可跨平台编译
    动态:python php nodejs
        需要一个解释器
        边解释边运行
        对运维很麻烦
        pyinstaller 弄成可执行文件
    强类型:
        不同类型之间不允许直接运算(所以要强制类型转换)
        go如何强制类型转换:显式类型转换
        Java:可以字符串+数字 但是是强类型语言--隐式类型转换、内部自动转换
    弱类型:js
        比如可以:字符串+数字
3 Go语言特性
    跨平台的编译型语言(交叉编译)
    语法接近C语言
    管道(channel),切片(slice),并发(routine)--》线程池+协程
    有垃圾回收的机制(GC机制)
    支持面向对象和面向过程的编程模式
        (继承,封装,多态)写法有点古怪
4 Go语言发展(版本/特性)
    // go语言也是用c写的
    //java,python都是用c写的
    2012年3月28日 go1 —— 稳定版版的发布
    2015年8月19日 go1.5 —— 实现的架构变化,同时保留了和旧版本的兼容性,本次更新中移除了”最后残余的C代码”---》自举
    2018年8月24日 go1.11 —— modules支持,摒弃掉go path的包管理
    2020 年 2 月 go 1.14— — 现在 Go Module 已经可以用于生产环境
    至今:1.17.6     开始支持泛型(额外操作)

5 go应用领域
    -服务端开发   高并发
    -微服务方向
    -区块链开发  第一款开源的区块链软件是用go写的
    -自动化运维 docker,k8s二开(docker、k8s是go写的,对go友好)
    -云平台
    -各个互联网公司都会招go开发
        -中小型公司跟风
    -前景:很广阔
        -以后自身有很好的未来:python、go、java(热门语言)都要会
    -go简单易学

2 静态和动态语言

c语言:按照c的语法写代码---->把源代码拿到Linux机器编译--》编译成Linux的可执行文件---》在Linux平台运行
java:一处编码处处运行,编译型语言
    -java的编译不是编译成可执行文件----》字节码文件,jar,war---》不能直接运行在操作系统之上(不是可执行文件)
    -java虚拟机:不同平台有不同平台的虚拟机,字节码文件运行在虚拟机之上
    -java的跨平台本质是不同平台装了不同平台的虚拟机---》有的人把它当成解释器
python:解释型----》python的源代码,运行在不同平台的解释器之上----》天然跨平台

php:解释型:php的解释器
nodejs: node环境

go:编译型,交叉编译(跨平台编译),只需要拿到编译好的可执行文件,直接运行即可

3 go开发环境搭建

// 搭建开发环境
// go的运行环境:不需要搭建---》可执行文件

// go的sdk----》内置函数,包,编译go源码(编译成可执行文件)
    -1.17 最新 ,向下兼容
    -下载地址:https://golang.google.cn/dl/
    -go1.17.6.windows-amd64.msi 一路下一步
    -安装完成后,会把安装路径加入到环境变量
        -go 命令,可以找到(如果没有装sdk,go可执行文件是没有的)

// 集成开发工具:推荐 goland
    -goland:推荐,收费,免费试用30天,老版本可以卡bug,无限试用30天
        -学生免费(教育邮箱)
        -开源软件作者免费(github开源持续多长时间提交代码)
        -花钱:单软件,多软件授权,多账号
        -破解:pycharm如何破,这个一样
        -下载地址:
            -https://www.jetbrains.com/zh-cn/go/download/other.html---》2021.1--》好破解
        -goland,pycharm,webstorm。。一家公司出的 Jetbrains
            -快捷键都一样,使用习惯都一样
        -安装:一路下一步
    -vs code
        -免费,有部分公司用,不涉及到版权问题
    -vim
        -装各种插件

// 验证环境搭建
    -打开cmd创建,输入
        -go version  // 查看版本信息
        -go env     // 查看go的环境变量

4 第一个go程序

// 新建的go项目内,有go.mod 文件,后面会讲,做包管理的

// 代码写好---》go是编译型语言----》编译成可执行文件----》运行可执行文件
// 运行方法:
    - go build go文件名字   // 编译go文件,编译成   go文件名字.exe
    - go文件名字.exe  可执行文件运行即可

// 开发阶段----》编译--》运行,比较麻烦,所以:
    -goland提供了,编译并运行---》右键---》run
    -原生提供了一个命令 (编译并运行的命令),但是编译后的文件,不在项目根路径下
        -go run go文件名字   

// ************第一个helloworld的代码***********

package main   // 指定包名,任何一个go文件都要有这句话,包名可以不一样,目前必须叫main

import "fmt" //导入内置包,fmt包,只要使用了fmt包,会自动导入,goland自动导入的,如果其他编辑器,需要手动导入

func main() {   // 定义一个函数,函数名叫 main,目前必须叫main
    fmt.Println("hello world")  // 真正的在控制台输出 hello world,必须用双引号
}

// 第一行,必须指定是main包
// 需要导入fmt包
// 程序要运行,必须写一个main函数,在main函数中打印helloworld

// 注意:go的项目入口:必须是main包下的main函数

// fmt.Println(a...)  是 goland给提示的东西,其实根本不存在,函数的参数提示,不用关注

5 语法和命名规范

// 第一行必须是包名
// 程序要运行,必须是main包下的main函数
    -一个项目中有一个main包,有两个main函数,它就不能运行,以后写项目肯定不能有俩main函数
    -学基础阶段,可以在一个项目下有多个main函数,但是必须以file形式运行,不能以包形式运行
// 包导入,goland可以自动导入,(后期可以手动导入)
// go build 只编译(在什么平台下就编译成什么平台的可执行文件)----》交叉编译
// go run   编译并运行


break      default       func     interface   select
case       defer         go       map         struct
chan       else          goto     package     switch
const      fallthrough   if       range       type
continue   for           import   return      var

// func 定义函数
// import 导入包
// package 声明包名
// var 定义变量的关键字

// 关键字不能作为变量的名字


内建常量: true false iota nil

内建类型:  int int8 int16 int32 int64
          uint uint8 uint16 uint32 uint64 uintptr
          float32 float64 complex128 complex64
          bool byte rune string error

内建函数: make len cap new append copy close delete
          complex real imag
          panic recover


// 以后定义变量时,不能以数字开头,可以使用数字字母下划线组成的字符串来定义
// 变量的大小写,有特殊含义,区分大小写
// 变量定义推荐用驼峰体
    -AgeOfPerson   go语言和java语言推荐,python不推荐
    -age_of_person  下划线方式,不推荐(go不推荐,python推荐)
// go文件的名字,建议使用下划线(参照源码)
    -java语言中:变量和文件名都推荐用驼峰
    -Python中:变量名和文件名都推荐用下划线

6 变量定义和使用

6 个点
    -变量完整定义
    -变量类型推导
    -变量简略声明
    -变量的使用,修改值,打印值
    -同时定义多个变量
    -变量要先定义,在使用,并且只能定义一次


// 变量的定义和使用

package main

import "fmt"

//var name = "lqz" // 作用域范围是全局,所有函数内部都可以使用

func main() {
    // 方式一:完整定义  var关键字 变量名 类型 = 变量值
    var NameOfCx string = "cx"  // 定义不使用会报错、编译阶段报错
    fmt.Println(NameOfCx)

    var age int = 19
    fmt.Println(age)

    // 方式二:类型推导(不需要写类型) var关键字 变量名 = 变量值
    var age2 = 19  // 没写类型、是推导出来的、也是固定不能改变
    fmt.Println(age2)

    var NameOfCx2 = "cx"
    fmt.Println(NameOfCx2)

    // 如何查看变量类型:Printf
    fmt.Printf("变量的类型:%T,变量值:%s", NameOfCx2,NameOfCx2)

    // 方式三:简略声明 变量名 := 变量值
    //age = 19  // 报错 变量没有定义
    age3 := 19
    fmt.Println(age3)
    fmt.Printf("%T  %d", age3, age3)

    // 变量的使用:修改值、打印值
    var name string = "cx"
    // 修改值 只能相同类型修改、在定义阶段就定义了类型、不能改类型
    name = "wyz"
    fmt.Println(name)

    //变量可以先定义再赋值
    var age4 int  // 只能使用方式一定义方式、不能推导
    age4 = 100
    fmt.Println(age4)

    // 一行同时定义多个变量:推导
    var name5, age5, gender5 = "cx", 19, "男"
    fmt.Println(name5, age5, gender5)

    // 一行同时定义多个变量:简略声明
    name6, age6, gender6 := "cx", 19, "男"
    fmt.Println(name6, age6, gender6)

    // 一行同时定义多个变量:var()
    var (
        name7 = "cx"
        age7 = 19
        gender7 = "男"
    )
    fmt.Println(name7, age7, gender7)

    // 变量要先定义 然后使用 并且只能定义一次
    // 使用简略声明可以定义多次,但是实际是修改值
    var age8 = 19
    name8,age8 := "cx",20  // 有定义、有修改、修改的定义是修改
    fmt.Println(age8, name8)
}

7 变量类型

// 基础数据类类型
    -数字
        -整型
            -int
            -int8
            -int16
            -int32
            -int64
        -正整数:无符号整型
            -uint
            -uint8
            -uint16
            -uint32
            -uint64
        -浮点型
            -float32
            -float64
        -复数(正常开发中用不到)
            -complex128
            -complex64
    -字符串
        -string
        -双引号或三引号包裹   (单引号不行:单引号表示数字)
    -布尔
        -bool
        -true false  (都是小写)

    -byte:uint8 的别名
    -rune:int32 的别名

// 复合数据类型
    -数组
    -切片
    -map
// 高级数据类型
    -自定义的类型
    -函数类型
    -指针类型


// 基础的变量类型
package main

func main() {
    // 1 整型(表示正负整数 和 0)

    // var age int = 19
    // int8 和其他区别在于,表示整数的范围不一样
    // var age int8 = -128
    // 一个int8 占8个比特位,8个小格只能放0或1,一个字节,所有它有2的8次方中变化,表示数字的大小2的7次方-1种变化
    // 正负2的7次方-1  -128----+127
    // int16 :正负2的15次方-1
    // int32:正负2的31次方-1
    // int64:正负2的63次方-1
    // int :分平台,在32位机器,表示int32,在64位机器表示int64
    // 以后,如果要定义一个变量,表示人的年龄
    // var age int = 9223372036854775807
    // fmt.Println(age)

    // 2 无符号整型

    // var age uint =19
    // fmt.Println(age)

    // uint8: 2的8次方-1   0---255之间
    // var age uint8=255
    // fmt.Println(age)
    // uint16:2的16次方-1
    // uint32:2的32次方-1
    // uint64:2的63次方-1
    // uint 在32位机器是 uint32,在64位机器是uint64

    // 3 浮点型(小数),表示精度不一样
    // var salary float32= 10.123456789   // 小数点后6位
    // var salary2 float64= 10.123456789123456789  // 小数点后15位
    // fmt.Println(salary)
    // fmt.Println(salary2)

    // 4 复数 ---》有实部6 和 虚部 7
    // var c complex64= 6 + 7i
    // var d complex64= 2 + 3i
    // fmt.Println(c+d)
    // 结果:实部相加、虚部相加

    // 5 字符串---》用双引号或反引号包裹---》反引号可以换行---->等同于python的三引号
    //    var  name = "lqz \n" +"is \n" + "nb"
    //    var  name2 = `彭于晏
    //                is
    //                    very
    //  handsome`
    //    fmt.Println(name)
    //    fmt.Println(name2)

    // 6 单引号,表示的类型是什么? 数字类型,int32,这个字符对应的unicode编码的数字,所以单引号只能放一个字符
    //var a ='A'   // unicode编码你对应的数字
    //var a int32='A'   // unicode编码你对应的数字
    //fmt.Println(a)
    //fmt.Printf("a的类型是:%T",a)  // a的类型是int32,它能够表示一个字符

    // 7 布尔类型---->if判断中经常用到
    //var b bool = true
    //var b1 bool = false
    //fmt.Println(b)
    //fmt.Println(b1)

    // 8 byte:uint8 的别名    -rune:int32 的别名
    //var a byte ='1'   // 最大长度 1个字节,8个比特位,255种变化,只能表示ascii
    //var b rune ='你'  // 4个字节,表示一个字符,可以放所有的象形文字
    //fmt.Println(a)
    //fmt.Println(b)
}

/*
Java与Go数字类型比较:

java:  byte   short   int    long      float      double
go:    int8   int16   int32  int64      float32    float64
python:int  float 不是基础数据类型,是对象
 */

8 常量和iota

// 常量:不变的量、定义后就不变了
//
package main

func main() {
    // 常量定义格式:
    // 1、const关键字 常量名 类型 = 值
    // 2、const关键字 常量名 = 值
    const name string="cx"
    const age = 19

    // 同时定义多个常量
    const name2, age2 = "cx", 19
    const (
        name3 = "cx"
        age3 = 18
    )
    const (
        a4 = 1
        b4  // 如果不赋值则遵从上面的赋值、相当于b4 = 1
        c4
    )

    // iota:是个自建常量  每换一行都会自增
    const (
        a5 = iota  // 等同于 a5=0
        b5
        c5
    )
    const (
        a6 = iota
        b6 = 100
        c6
        d6
        e6 = iota
    )  // 0 100 100 100 4

// 注意:
//同时定义多个常量,如果下一行只写常量名,遵从上一行的赋值方式
// iota每换一行,就会自增1,无论用还是不用
}

9 函数基础

// 函数基础

package main

import "fmt"

/*
注意:函数定义后可以不使用
1 定义函数基础语法:
    func关键字 函数名(形参1 形参1类型,形参2 形参2类型)(返回值类型){
        函数体内容(与缩进无关、括号内都是函数体内容)
    }
*/

// 2 简单的函数定义、无参数无返回值
func test() {
    fmt.Println("我是test")
}

// 3 定义有参数、无返回值函数、参数类型相同
func test2(x int,y int)  {
    fmt.Println(x)
}

// 4 定义有参数、无返回值、参数类型相同
func test3(a, b int, c,d string)  {
    fmt.Println(a,b,c,d)
}

// 5 定义有2参数、有1个返回值 -- return
func test4(a,b int) int {
    c := a+b
    return c

}

// 6 定义2个参数、2个返回值
func test5(a, b int) (int,int) {
    c := a+b
    d := a*b
    return c,d
}

// 7 命名返回值,函数体不用重新定义
func test6(a, b int) (add int, mul int) {
    add = a+b
    mul = a*b
    return  // return可以直接省略add、mul
}

func main() {
    // 在main调用函数
    fmt.Println("s5开始执行了")
    test()
    test2(10, 20)  // 只有位置传参、没有关键字传参、没有默认参数(有几个参数就传几个)
    test3(10,20,"cx","ll")
    // 接收1个返回值
    var a = test4(5,6)
    b := test4(1,2)
    fmt.Println(a,b)
    // 接收两个返回值
    a2,b2 := test5(6,6)
    fmt.Println(a2,b2)
    // 有多个返回值只接收1个、如果用变量接收但不实用、会报错
    // _接收,不使用也不会报错
    a3,_:=test5(4,5)
    fmt.Println(a3)

    // 命名返回值的使用
    add,mul := test6(1,2)
    fmt.Println(add,mul)
}

10 函数高级

// 函数高级

package main

import "fmt"

// 注意:Go以包作为最小单位、所以函数名不能和同个包的函数重名
// 1 可变长参数
// 可接收任意长度int类型的参数
func test7(a ...int) {
    fmt.Println(a)  // 切片
}

// 2 匿名函数:在main里

/*
3 函数也是一种类型--是一等公民/头等函数  go、python是  Java不是
    指:可以把函数当变量使用

4 函数是变量 就可以当参数传递、当返回值返回

5 闭包函数:必须符合两个条件:
    1、定义在函数内部
    2、对外部作用域有引用
    go有闭包函数、可以做出装饰器来 但是没有语法糖语法
*/

func test8() func() {
    name := "cx"
    a:=func(){
        fmt.Println("内层函数")
        fmt.Println(name)
    }
    return a

}

// 6 尽量要看懂:函数是变量 就可以当参数传递、当返回值返回
// 函数是一种类型、函数的参数和返回值都是类型的一部分
func test9(aa int) func(a int,b func())(int,func()){

    return func(a int,b func())(int,func()) {
        fmt.Println("我是内层函数")
        return a, func() {}
    }
}

// 7 给类型重命名
type MyFunc func(a int,b func())(int,func())

func test10() MyFunc {
    return func(a int,b func())(int,func()) {
        fmt.Println("我是内层函数")
        return a, func() {}
    }
}

func main() {
    // 与python
    test7(1,2,3,4,5)

    // 2 定义在函数内部的函数,必须是匿名函数
    // 2.1 无参数
    func (){
        fmt.Println("我是匿名函数")
    }()  // 要执行否则报错
    // 2.2 有参数
    func (a,b int){
        fmt.Println("我是匿名函数")
    }(1,2)
    // 2.3 有参数 有返回值
    var a,b = func (a,b int)(int,int){
        fmt.Println("我是匿名函数")
        return a,b
    }(1,2)
    fmt.Println(a,b)

    // 3 函数是一等公民 --> 可以把函数赋值给一个变量
    var f = func (){
        fmt.Println("我是匿名函数")
    }
    fmt.Println(f)  // 内存地址
    f()  // 调用
    fmt.Printf("type:%T", f)

    // 4、5闭包
    var f2 func()=test8()
    f2()

    // 调用test9
    // 方式一:
    var f3 func(a int,b func())(int,func()) = test9(11)
    f3(1,f2)
    // 方式二:
    var f4=test9(11)
    f4(1,f2)
    // 方式三:
    f5:=test9(11)  // 简略声明会方便很多、最常用
    f5(1,f2)
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章