• ch4、编写第一个Go程序


    ch4、编写第一个Go程序

    1、设置环境变量

    • Go中需要配置三个环境变量,分别是:

      • GOROOT:Go的安装目录

      • PATH:Go的安装目录下的bin目录

      • GOPATH:Go的项目目录

        • 在 1.8 版本前必须设置这个环境变量
        • 1.8 版本后(含 1.8)如果没有设置,会使用默认值
          • 在 Unix 上默认为 $HOME/go , 在 Windows 上默认为 %USERPROFILE%/go;
          • 在 Mac 上 GOPATH 可以通过修改 ~/.bash_profile 来设置;

    【注意】将GOROOT和PATH配置到系统的环境变量中,但是GOPATH不直接在系统变量中配置成一个固定的配置,因为我们可能在一个系统中创建多个Go项目,每一个项目都需要配置一个GOPATH变量,这显然是繁琐而且非常难以管理的,所以我们在创建项目的时候,直接通过IDE在创建项目的时候来配置GOPATH变量,这样就可以给每个Go项目都配置上对应的GOPATH路径。

    在这里插入图片描述

    2、新建项目

    在这里插入图片描述

    3、编写第一个go程序代码:

    package main
    
    import (
      "fmt"
      "os"
    )
    
    func main() {
      fmt.Println(os.Args)
      if len(os.Args) > 1 {
        fmt.Println("Hello World ", os.Args[1])
      }
      os.Exit(-1)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 必须是 main 包: package main
    • 必须是 main 方法: func main()
    • 文件名不一定是 main.go
    • 退出返回值

      • Go 中 main 函数不支持任何返回值
      • 通过 os.Exit 来返回状态
    • 与其他主要编程语言的差异

      • main 函数不支持传入参数,以下用法错误
        func main(arg []string)
        
        • 1
      • 在程序中直接通过 os.Args 获取命令⾏行行参数,另外一种方法是通过flag包来获取命令行参数(推荐用这种)

    4、Go语言编码风格

    • go程序编写在.go为后缀的文件中
    • 包名一般使用文件所在文件夹的名称
    • 包名应该简洁、清晰且全小写
    • main函数只能编写在main包中
    • 每一条语句后面可以不用编写分号(推荐)
    • 如果没有编写分号,一行只能编写一条语句
    • 函数的左括号必须和函数名在同一行
    • 导入包但没有使用包编译会报错
    • 定义局部变量但没有使用变量编译也会报错
    • 定义函数但没有使用函数不会报错
    • 给方法、变量添加说明,尽量使用单行注释

    5、go语言的输入输出

    fmt标准包

    5.1、输出函数

    • Go语言fmt包实现了类似C语言printf和scanf的格式化I/O, 格式化动作源自C语言但更简单,输出函数
    func Printf(format string, a ...interface{}) (n int, err error)
    
    • 1
    • 可以通过%o、%x输出八进制和十六进制外,还可以直接通过%b输出二进制,更多格式设置见fmt标准包的官方文档说明
    package main
    import "fmt"
    func main() {
        num := 15
        fmt.Printf("十进制 = %d\n", num)
        fmt.Printf("八进制 = %o\n", num)
        fmt.Printf("十六进制 = %x\n", num)
        fmt.Printf("二进制 = %b\n", num)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 除此之外,Go语言还增加了%T控制符, 用于输出值的类型
    package main
    import "fmt"
    func main() {
      type Person struct {
      	name string
      	age int
      }
      num1 := 10
      num2 := 3.14
      per := Person{"lnj", 33}
      fmt.Printf("num1 = %T\n", num1) // int
      fmt.Printf("num2 = %T\n", num2) // float64
      fmt.Printf("per = %T\n", per) // main.Person
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 除此之外,Go语言还增加了%v控制符,用于打印所有类型数据
      • Go语言中输出某一个值,很少使用%d%f等, 一般都使用%v即可
      • 输出复合类型时会自动生成对应格式后再输出
    package main
    import "fmt"
    func main() {
      type Person struct {
      	name string
      	age int
      }
      num1 := 10
      num2 := 3.14
      per := Person{"lnj", 33}
      // 此时相当于把%v当做%d
      fmt.Printf("num1 = %v\n", num1) // 10
      // 此时相当于把%v当做%f
      fmt.Printf("num2 = %v\n", num2) // 3.14
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • func Println(a …interface{}) (n int, err error)

      • 采用默认格式将其参数格式化并写入标准输出
        • 输出之后在结尾处添加换行
        • 传入多个参数时, 会自动在相邻参数之间添加空格
        • 传入符合类型数据时, 会自动生成对应格式后再输出
      package main
      import "fmt"
      func main() {
        num1 := 10
        num2 := 3.14
        fmt.Println(num1, num2) // 10 3.14
        fmt.Println("num1 =", num1, "num2 =", num2) // num1 = 10 num2 = 3.14
      
        type Person struct {
        	name string
        	age int
        }
        per := Person{"lnj", 33}
        fmt.Println(per) // {lnj 33}
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
    • func Print(a …interface{}) (n int, err error)

      • 和Println几乎一样
        • 输出之后不会在结尾处添加换行
        • 传入多个参数时, 只有两个相邻的参数都不是字符串,才会在相邻参数之间添加空格
        • 传入符合类型数据时, 会自动生成对应格式后再输出
      package main
      import "fmt"
      func main() {
        num1 := 10
        num2 := 3.14
        fmt.Print(num1, num2) // 10 3.14
        fmt.Print("num1 =", num1, "num2 =", num2) // num1 =10 num2 =3.14
      
        type Person struct {
        	name string
        	age int
        }
        per := Person{"lnj", 33}
        fmt.Print(per) // {lnj 33}
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
    • 以下三个函数和Printf/Println/Print函数一样, 只不过上面三个函数是输出到标准输出, 而下面三个函数可以通过w指定输出到什么地方

      • func Fprintf(w io.Writer, format string, a …interface{}) (n int, err error)
      • func Fprintln(w io.Writer, a …interface{}) (n int, err error)
      • func Fprint(w io.Writer, a …interface{}) (n int, err error)
    package main
    import (
    	"fmt"
    	"net/http"
    	"os"
    )
    func main() {
    	// os.Stdout 写入到标准输出
    	name := "lnj"
    	age := 33
    	// 第一个参数: 指定输出到什么地方
    	// 第二个参数: 指定格式控制字符串
    	// 第三个参数: 指定要输出的数据
    	fmt.Fprintf(os.Stdout, "name = %s, age = %d\n", name, age)
    
    	// http.ResponseWriter 写入到网络响应
    	http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
    		fmt.Fprintf(writer, "name = %s, age = %d\n", name, age)
    	})
    	http.ListenAndServe(":8888", nil)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 以下三个函数和Printf/Println/Print函数一样, 只不过上面三个函数是输出到标准输出,而下面三个函数是将字符串返回
      • func Sprintf(format string, a …interface{}) string
        • func Sprint(a …interface{}) string
        • func Sprintln(a …interface{}) string
    package main
    import (
    	"fmt"
    	"net/http"
    	"os"
    )
    func main() {
    	name := "lnj"
    	age := 33
    	// 按照指定的格式生成字符串
    	str := fmt.Sprintf("name = %s, age = %d\n", name, age)
    	// 输出生成的字符串
    	fmt.Println(str)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    5.2、输入函数

    • func Scanf(format string, a …interface{}) (n int, err error)

      package main
      import "fmt"
      func main() {
          var num1 int
          var num2 int
          fmt.Scanf("%d%d", &num1, &num2)
          fmt.Println(num1, num2)
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • func Scan(a …interface{}) (n int, err error)

      • 和C语言scanf函数几乎一样, 只不过不用指定格式化字符串
      package main
      import "fmt"
      func main() {
        var num1 int
        var num2 int
        fmt.Scan(&num1, &num2)
        fmt.Println(num1, num2)
      
        var num3 float32
        var num4 float32
        fmt.Scan(&num3, &num4)
        fmt.Println(num3, num4)
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
    • func Scanln(a …interface{}) (n int, err error)

      • 和C语言用法几乎一模一样, 只不过不用指定格式化字符串, 并且只能输入一行数据
      package main
      import "fmt"
      func main() {
          var num1 int
          var num2 int
          fmt.Scanln(&num1, &num2)
          fmt.Println(num1, num2)
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • 以下三个函数和Scan/Scanln/Scanf函数一样, 只不过上面三个函数是从标准输入读取数据, 而下面三个函数可以通过r指定从哪读取数据

      • func Fscanf(r io.Reader, format string, a …interface{}) (n int, err error)
      • func Fscanln(r io.Reader, a …interface{}) (n int, err error)
      • func Fscan(r io.Reader, a …interface{}) (n int, err error)
    package main
      import "fmt"
      func main() {
    	  var num1 int
    	  var num2 int
    	  // 第一个参数: 指定从哪读取数据
    	  // 第二个参数: 指定格式控制字符串
    	  // 第三个参数: 指定要输出的数据
    	  fmt.Fscanf(os.Stdin, "%d%d", &num1, &num2)
    	  fmt.Println(num1, num2)
    
    
    	  s := strings.NewReader("lnj 33")
    	  var name string
    	  var age int
    	  // 从指定字符串中扫描出想要的数据
    	  // 注意:
    	  fmt.Fscanf(s, "%s%d", &name, &age)
    	  fmt.Println("name =",name, "age =",age)
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 以下三个函数和Scan/Scanln/Scanf函数一样, 只不过上面三个函数是通过r指定从哪读取数据, 而下面三个函数是从字符串中读取数据
      • func Sscan(str string, a …interface{}) (n int, err error)
      • func Sscanf(str string, format string, a …interface{}) (n int, err error)
      • func Sscanln(str string, a …interface{}) (n int, err error)
    package main
      import "fmt"
      func main() {
    	str := "lnj 33"
    	var name string
    	var age int
    	//fmt.Sscanf(str, "%s %d",&name, &age)
    	//fmt.Sscanln(str,&name, &age)
    	fmt.Sscan(str,&name, &age)
    	fmt.Println("name =",name, "age =",age)
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    场景:如何从标准输入读取带空格的字符串?

    方法:使用bufio包里带缓冲的Reader实现带空格字符串的输入

    package intout
    
    import (
    	"bufio"
    	"fmt"
    	"os"
    	"strconv"
    	"strings"
    )
    
    func ReadFromASpaceString() {
    	inputReader := bufio.NewReader(os.Stdin)
    	fmt.Println("Please input your name: ")
    	//input, err := inputReader.ReadBytes('\n')
    	input, err := inputReader.ReadString('\n')
    	if err == nil {
    		//fmt.Printf("Your bname is :%s, and type is %T\n", input, input)
    		//ss := strings.Split(input, " ")
    		ss := strings.Trim(input, "\n")
    		ss1 := strings.Split(ss, " ")
    		fmt.Printf("Your name is :%v, and type is %T\n", ss,
    			ss)
    		fmt.Printf("Your name is :%v, and type is %T\n", ss1, ss1)
    		fmt.Printf("Your name is :%v, and type is %T\n", ss1[0], ss1[0])
    		num1, err := strconv.Atoi(ss1[0])
    		if err != nil {
    			fmt.Println(err)
    		}
    		fmt.Printf("Your name is :%v, and type is %T\n", num1, num1)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    6、go命令行操作指令

    • 标准go语言项目文件目录格式
      • 项目文件夹就是GOPATH指向的文件夹
      • src文件夹是专门用于存放源码文件的
        • main文件夹是专门用于存储package main包相关源码文件的
        • 其它文件夹是专门用于存储除package main包以外源码文件的
      • bin文件夹是专门用于存储编译之后的可执行程序的
      • pag文件夹是专门用于存储编译之后的.a文件的

    |—项目文件夹
    -----------|--------src文件夹
    -----------------------------|--------main文件夹
    -----------------------------|--------其它文件夹
    -----------|--------bin文件夹
    -----------|--------pkg文件夹

    • go version 查看当前安装的go版本

    • go env 查看当前go的环境变量

    • go fmt 格式化代码

      • 会将指定文件中凌乱的代码按照go语言规范格式化
    • go run 命令文件 编译并运行go程序

      • package main包中包含main函数的文件, 我们称之为命令文件
      • 其它包中的文件, 我们称之为源码文件
    • go build 编译检查

      • 对于非命令文件只会执行编译检查, 不会产生任何文件
      • 对于命令文件除了编译检查外,还会在当前目录下生成一个可执行文件
      • 对应只想编译某个文件, 可以在命令后面指定文件名称go build 文件名称
    • go install 安装程序

      • 对于非命令文件会执行编译检查, 并生成.a结尾的包, 放到 $GOPATH/pkg目录中
        ion` 查看当前安装的go版本
    • go env 查看当前go的环境变量

    • go fmt 格式化代码

      • 会将指定文件中凌乱的代码按照go语言规范格式化
    • go run 命令文件 编译并运行go程序

      • package main包中包含main函数的文件, 我们称之为命令文件
      • 其它包中的文件, 我们称之为源码文件
    • go build 编译检查

      • 对于非命令文件只会执行编译检查, 不会产生任何文件
      • 对于命令文件除了编译检查外,还会在当前目录下生成一个可执行文件
      • 对应只想编译某个文件, 可以在命令后面指定文件名称go build 文件名称
    • go install 安装程序

      • 对于非命令文件会执行编译检查, 并生成.a结尾的包, 放到 $GOPATH/pkg目录中
      • 对于命令文件会执行编译检查, 并生成可执行程序, 放到$GOPATH/bin目录中
  • 相关阅读:
    PHP语言基础知识,电商API代码生成
    (其他) 剑指 Offer 65. 不用加减乘除做加法 ——【Leetcode每日一题】
    聊聊logback的DuplicateMessageFilter
    Synopsys Sentaurus TCAD系列教程之-Tcl《3》
    645. 错误的集合
    XSS初级漏洞靶场
    33.【C/C++ char 类型与Ascii大整合,少一个没考虑你打我】
    LeetCode --- 1380. Lucky Numbers in a Matrix 解题报告
    【精选】JSP技术知识点大合集
    深度学习(二)BERT模型及其一系列衍生模型
  • 原文地址:https://blog.csdn.net/u012558127/article/details/125630618