Go 语言基础之常用包【flag、time、strconv、io】

news2024/11/25 9:40:24

1、命令行参数包 flag 

flag 包就是一个用来解析命令行参数的工具。

1.1、os.Args

import (
	"fmt"
	"os"
)

func main() {
	if len(os.Args) > 0 {
		for index, arg := range os.Args {
			fmt.Printf("args[%d]=%v\n", index, arg)
		}
	}
}

运行结果:

        osArgs 的本质是一个字符串切片,它的第一个索引 0 存储的是可执行文件的名称,之后的参数才是用户输入的参数。

1.2、flag 包的基本使用

flag 支持的的命令行参数主要有:数值类型、字符串和时间间隔(time.Duration)等。

  • 对于 duration 类型,合法的单位有"ns"、“us” 、“µs”、“ms”、“s”、“m”、“h”。用的时候需要带上单位,比如 1h30m。

1.2.1、命令行参数的定义

        命令行参数的定义有两种方式:一种是不带初始值的(flag.Type),一种是带初始值的(flag.TypeVar)。

flag.Type(flag名, 默认值, 帮助信息)
    name := flag.String("name", "张三", "姓名")
	age := flag.Int("age", 18, "年龄")
	married := flag.Bool("married", false, "婚否")
	delay := flag.Duration("delay", 0, "时间间隔")

通过查看源码我们可以发现,使用这种方式返回的是一个指针,而不是值:

所以在读取的时候需要使用 * 来取出指针的值。 

flag.TypeVar(Type指针, flag名, 默认值, 帮助信息)
var name string
var age int
var married bool
var delay time.Duration
flag.StringVar(&name, "name", "张三", "姓名")
flag.IntVar(&age, "age", 18, "年龄")
flag.BoolVar(&married, "married", false, "婚否")
flag.DurationVar(&delay, "d", 0, "时间间隔")

1.2.2、解析命令行参数 flag.Parse()

定义好命令行参数之后,需要显式调用解析命令行参数方法(flag.Parse())才能生效,不然读取不到参数。

flag 支持的命令行参数格式有以下几种:

  • -flag xxx (使用空格,一个-符号)
  • --flag xxx (使用空格,两个-符号)
  • -flag=xxx (使用等号,一个-符号)
  • --flag=xxx (使用等号,两个-符号)

对于布尔类型的参数一般用等号来传递,不然解析不到布尔值之后的参数,并且会把布尔值及其之后的参数当做其它参数。

使用 go run ./flag.go 执行或者 go build 编译 go 文件再执行:

​​go build ./flag.go

1.2.3、其它参数 

        除了我们定义的参数之外,还可以有其它参数,但是必须跟在我们定义的最后一个参数后面,此外 flag 提供了一些方法来获取其它参数的属性:

	//返回命令行参数后的其他参数
	fmt.Println(flag.Args())
	//返回命令行参数后的其他参数个数
	fmt.Println(flag.NArg())
	//返回使用的命令行参数个数
	fmt.Println(flag.NFlag())

1.3、测试

package main

import (
	"flag"
	"fmt"
	"time"
)

func main() {
	var age int
	var married bool
	var delay time.Duration
	name := flag.String("name", "张三", "姓名")
	flag.IntVar(&age, "age", 18, "年龄")
	flag.BoolVar(&married, "married", false, "婚否")
	flag.DurationVar(&delay, "delay", 0, "延迟的时间间隔")

	//解析命令行参数
	flag.Parse()
	
	fmt.Println(*name, age, married, delay)
	
	//返回命令行参数后的其他参数
	fmt.Println(flag.Args())
	//返回命令行参数后的其他参数个数
	fmt.Println(flag.NArg())
	//返回使用的命令行参数个数
	fmt.Println(flag.NFlag())
}

测试1(自定义参数 + 其它参数): 

测试2(全为其它参数):

2、时间包 time

Go 语言中使用time.Time类型表示时间。我们可以通过time.Now函数获取当前的时间对象,然后从时间对象中可以获取到年、月、日、时、分、秒等信息。

func main() {
	now := time.Now()
	// 2024-05-06 19:44:56.6410767 +0800 CST m=+0.004404001
	fmt.Println(now)
	// 现在是2024年5月6日19时46分38秒
	fmt.Printf("现在是%d年%d月%d日%d时%d分%d秒", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second())
}

2.1、Location和time zone

这个还是比较实用的,因为 time.LoadLocation 依赖系统的时区数据库,在不太确定程序运行环境的情况下建议先自定义时区偏移量(比如北京时间就是东八区时间,需要在UTC基础上+8个小时)然后使用time.FixedZone的方式指定时区。

    // 时差(单位:s)
	diffSeconds := int((8 * time.Hour).Seconds()) // float 转 int
	// 北京时间
	beijing := time.FixedZone("Beijing Time", diffSeconds) // 返回 *Location

2.2、Unix Time

        Unix Time是自1970年1月1日 00:00:00 UTC 至当前时间经过的总秒数,我们可以通过 time 提供的方法获得当前的 Unix 秒/毫秒数(微秒、纳秒用不上):

func main() {
	now := time.Now()
    // 都是返回 int64 类型的整数
	timestamp := now.Unix()
	millisecond := now.UnixMilli() 
	// 1714996867s,1714996867336ms
	fmt.Printf("%ds,%dms", timestamp, millisecond) 
}

我们也可以把秒/毫秒数(int64)转为时间:

func main() {
	now := time.Now()
    // 都是返回 int64 类型的整数
	second := now.Unix()
    // 第2个参数为不足1秒的纳秒数
	timeValue := time.Unix(int64(second), 22)
	fmt.Println(timeValue) // 2024-05-06 20:01:07.000000022 +0800 CST
}

2.3、时间间隔 

time 包中定义的时间间隔类型的常量如下:

const (
    Nanosecond  Duration = 1
    Microsecond          = 1000 * Nanosecond
    Millisecond          = 1000 * Microsecond
    Second               = 1000 * Millisecond
    Minute               = 60 * Second
    Hour                 = 60 * Minute
)

用的时候直接用常量 * 单位即可,下面是 time.Duration 常用的一些方法:


func main() {
	now := time.Now()
	// 这里 Add 方法的参数为 time.Duration 类型
	later := now.Add(3 * time.Hour)
	// 三个小时以后是: 2024-05-06 23:07:28.3043137 +0800 CST m=+10800.004676401
	fmt.Println("三个小时以后是: ", later)
	// Sub 方法的返回值为 time.Duration 类型
	fmt.Println(now.Sub(later)) // -3h0m0s
	// now 是否在 later 之前
	fmt.Println(now.Before(later)) // true
	// now 是否在 later 之后
	fmt.Println(now.After(later)) // false

	// 加载东京所在的时区
	tokyo, _ := time.LoadLocation("Asia/Tokyo")
	// 加载上海所在的时区
	shanghai, _ := time.LoadLocation("Asia/Shanghai")
	tk := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), now.Nanosecond(), tokyo)
	sh := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), now.Nanosecond(), shanghai)
	// 判断两个时间是否相同,会考虑时区的影响
	fmt.Println(now.Equal(tk)) // false
	fmt.Println(now.Equal(sh)) // true
}

2.4、时间格式化

注意:Go 语言诞生于2006 年 1 月 2 日下午15 点 4 分 5 秒,它的时间格式化模板用的也正是这个时间!

func main() {
	now := time.Now()
	// 格式化模板:2006-01-02 15:04:05.000
	fmt.Println(now.Format("2006-01-02 15:04:05")) // 2024-05-06 20:24:57
}

2.5、解析时间字符串 

func main() {
	now := time.Now()
	// 格式化模板:2006-01-02 15:04:05.000
	// 两个参数的长度必须对应上
	t1, _ := time.Parse("2006-01-02 15:04:05", now.String()[0:19])
	fmt.Println(t1) // 2024-05-06 20:34:59 +0000 UTC
}

在解析时,可额外指定时区信息:

func main() {
	now := time.Now()
	sh, _ := time.LoadLocation("Asia/Shanghai")
	// 格式化模板:2006-01-02 15:04:05.000
	// 按照指定时区和指定格式解析字符串时间
	t1, _ := time.ParseInLocation("2006-01-02 15:04:05", now.String()[0:19], sh)
	fmt.Println(t1) // 2024-05-06 20:40:24 +0800 CST
}

3、strconv

Go 语言中 strconv 包实现了基本数据类型和其字符串表示的相互转换,主要有以下常用函数: Atoi()、Itoa()、parse系列、format系列、append系列。

3.1、string 转 int(Atoi)

        为什么是 Atoi 而不是 Atos 呢?这是因为C语言中没有string类型而是用字符数组(array)表示字符串。

func main() {
	str := "100"
	num, _ := strconv.Atoi(str)
	fmt.Printf("%T,%v", num, num) // int,100
}

3.2、int 转 string(Itoa)

func main() {
	num := 100
	str := strconv.Itoa(num)
	fmt.Printf("%T,%v", str, str) // string,100
}

3.3、Parse 系列

        Parse类函数用于转换字符串给定类型的值:ParseBool()、ParseFloat()、ParseInt()、ParseUint()。

	b, _ := strconv.ParseBool("true")
	f, _ := strconv.ParseFloat("3.1415", 64)
	i, _ := strconv.ParseInt("-2", 10, 64)
	u, _ := strconv.ParseUint("2", 10, 64)

3.4、Format 系列

Format系列函数实现了将给定类型数据格式化为string类型数据的功能。

s1 := strconv.FormatBool(true)
s2 := strconv.FormatFloat(3.1415, 'E', -1, 64)
s3 := strconv.FormatInt(-2, 16)
s4 := strconv.FormatUint(2, 16)

这里需要特别说明的是:

func FormatFloat(f float64, fmt byte, prec, bitSize int) string
  • fmt 表示格式:‘f’(-ddd.dddd)、‘b’(-ddddp±ddd,指数为二进制)、’e’(-d.dddde±dd,十进制指数)、‘E’(-d.ddddE±dd,十进制指数)、‘g’(指数很大时用’e’格式,否则’f’格式)、‘G’(指数很大时用’E’格式,否则’f’格式)。

  • prec 控制精度(排除指数部分):对’f’、’e’、‘E’,它表示小数点后的数字个数;对’g’、‘G’,它控制总的数字个数。如果prec 为-1,则代表使用最少数量的、但又必需的数字来表示f。

3.5、其它方法

func CanBackquote(s string) bool

表示返回字符串s是否可以不被修改的表示为一个单行的、没有空格和tab之外控制字符的反引号字符串。

4、文件操作

        计算机中的文件是存储在外部介质(通常是磁盘)上的数据集合,文件分为文本文件和二进制文件(音频、视频)等。

4.1、文件的打开与关闭

    // 返回文件对象指针和error对象
	file, _ := os.Open("./main.go")
	defer file.Close()

4.2、普通方式读取文件

读取文件的方法源码:

func (f *File) Read(b []byte) (n int, err error)

其中,b 是一个用于存放文件读取进来的字节,相当于是一个缓冲区,可以重复使用。

func main() {
	file, _ := os.Open("./main.go")
	defer file.Close()

	// 开辟一个大小为128的字节切片用来存储文件
	tmp := make([]byte, 128)
	n, err := file.Read(tmp)
	if err == io.EOF {
		fmt.Println("读取完毕")
		return
	}
	if err != nil {
		fmt.Println("读取失败")
		return
	}
	fmt.Printf("读取了%d字节的数据\n", n)
	fmt.Println(string(tmp[:n]))
}

        这种方式读取的缺点是我们并不能知道文件的大小,如果定义的缓冲区太大就浪费资源了,但是定义小了又读取不完整(因为只能读一次,不能循环利用),所以我们更多的是使用下面这种循环读取的方式:

func main() {
	file, _ := os.Open("./main.go")
	defer file.Close()

	var content []byte
	// 开辟一个大小为128的字节切片用来存储文件
	tmp := make([]byte, 128)
	for {
		n, err := file.Read(tmp)
		if err == io.EOF {
			fmt.Println("读取完毕")
			break
		}
		if err != nil {
			fmt.Println("读取失败")
			return
		}
		content = append(content, tmp[:n]...)
	}
	fmt.Println(string(content))
}

 这种方法每次都会从文件读取 128 字节数据,Read 方法的返回值是一个切片,所以需要使用 append 函数来汇总到 content 切片当中;从下一次读取,又会把上一次的结果覆盖掉,

4.3、使用 bufio 读取文件

bufio 是在 file 的基础上封装了一层API,支持更多的功能:

func main() {
	file, _ := os.Open("./main.go")
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		fmt.Println(scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		fmt.Println("读取失败", err)
	}
}

4.4、使用 os.ReadFile 读取整个文件

os包(go1.16之前是 io.ioutil )的ReadFile方法能够读取完整的文件,只需要将文件名作为参数传入:

func main() {
	content, err := os.ReadFile("./main.go")
	if err != nil {
		fmt.Println("读取失败")
		return
	}
	fmt.Println(string(content))
}

4.5、文件写入操作

os.OpenFile()函数能够以指定模式打开文件,从而实现文件写入相关功能:

func OpenFile(name string, flag int, perm FileMode) (*File, error) {
	...
}

其中 name:要打开的文件名 flag:打开文件的模式。 模式有以下几种:

模式含义
os.O_WRONLY 只写
os.O_CREATE创建文件
os.O_RDONLY 只读
os.O_RDWR读写
os.O_TRUNC清空
os.O_APPEND追加

4.5.1、Write 和 WriteString 

func main() {
	// 0666是文件的权限设置,表示文件所有者、所属组和其他用户都有读写权限
	file, err := os.OpenFile("./test.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println("操作文件失败", err)
		return
	}
	defer file.Close()
	str := "Hello let's Go\n"
	file.Write([]byte(str))
	file.WriteString("Hello Big Data")
}

运行结果:

4.5.2、bufio.NewWriter

效果都是一样的,只不过是不同包下的方法:

func main() {
	// 0666是文件的权限设置,表示文件所有者、所属组和其他用户都有读写权限
	file, err := os.OpenFile("./test.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println("操作文件失败", err)
		return
	}
	defer file.Close()
	writer := bufio.NewWriter(file)
	for i := 0; i < 10; i++ {
		writer.WriteString("Hello let's Go\n") //将数据先写入缓存
	}
	writer.Flush() // 将缓存中的内容写入文件
}

4.5.3、os.WriteFile

        os 包(go1.16之前是 io.ioutil )下的 WriteFile 可以一次将一个byte切片内的数据全部写入文件当中。只不过不能指定写入模式,比如追加等。

func main() {
	str:="Hello let's Go"
	err := os.WriteFile("./test.txt", []byte(str), 0666)
	if err != nil {
		fmt.Println("写入失败")
		return
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1660346.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开源交互审计系统:功能强大、安全好用【送源码】

在当今信息化时代&#xff0c;网络安全越来越受到重视。传统的远程控制工具&#xff0c;如RDP、SSH、VNC等&#xff0c;虽然方便易用&#xff0c;但存在安全隐患&#xff0c;容易被黑客利用。很多时候我们都需要做一些防护的处理来来保障网络安全。 今天了不起来分享一款开源好…

CSS跳动文字

<div class"loading-mask"><div class"loading-text"><span style"--i:1">加</span><span style"--i:2">载</span><span style"--i:3">中</span><span style"--i:…

JavaScript数组(Array)方法 - toReversed、toSorted、toSpliced

最近发现几个数组方法&#xff0c;是一些常规方法的升级版&#xff0c;比较有意思&#xff0c;分享给大家 文章目录 一、温故二、知新toReversedtoSortedtoSpliced 一、温故 我们先来回顾几个比较常用的方法&#xff1a;reverse&#xff0c;sort&#xff0c;splice众所周知&a…

.NET WebService \ WCF \ WebAPI 部署总结 以及 window 服务 调试

一、webservice 部署只能部署IIS上&#xff0c; 比较简单&#xff0c;就不做说明了 二、 WCF 部署 1 部署到IIS 跟部署 webservice 部署方法一样的 wcf 部署2 部署到控制台 要以管理员运行vs&#xff0c;或者 管理员运行 控制台的exe 在控制器项目中 创建IUserInfoService 接口…

Sqli-labs第五,六关

目录 首先找到他们的闭合方式 操作 总结&#xff1a; 第五关根据页面结果得知是字符型但是和前面四关还是不一样是因为页面虽然有东西。但是只有对于请求对错出现不一样页面其余的就没有了。这个时候我们用联合注入就没有用&#xff0c;因为联合注入是需要页面有回显位。如果…

漫威争锋Marvel Rivals怎么搜索 锁区怎么搜 游戏搜不到怎么办

即将问世的《漫威争锋》&#xff08;Marvel Rivals&#xff09;作为一款万众期待的PvP射击游戏新星&#xff0c;荣耀携手漫威官方网站共同推出。定档5月11日清晨9时&#xff0c;封闭Alpha测试阶段将正式揭开序幕&#xff0c;持续时间长达十天之久。在此首轮测试窗口&#xff0c…

神经网路与深度学习

1 深度学习简述 机器学习&#xff1a;相当于把公式实现出来了而已。 深度学习&#xff1a; &#xff08;1&#xff09;中的特征工程使机器学习更智能。 &#xff08;2&#xff09;真正能学什么样的特征才是最合适的。 &#xff08;3&#xff09;主要应用于计算机视觉和自然语…

QA测试开发工程师面试题满分问答22: (干货)为什么要加锁Lock,举个例子说说

加锁原因 下面代码会有什么问题&#xff1f; import threading import requests from queue import Queuedef make_request(url, params, results_queue):response requests.get(url, paramsparams)result {url: url,params: params,response: response.text}results_queue…

官方文档k8s1.30安装部署高可用集群,kubeadm安装Kubernetes1.30最新版本

文章目录 节点架构一、准备开始(每一台机器都执行)1️⃣ 检查所需端口(可以直接关闭防火墙放开所有端口)端口和协议控制面工作节点 关闭防火墙关闭 SELinux 2️⃣ 安装containerd容器containerd部署containerd切换为国内源 3️⃣ 设置/etc/hosts 二、安装 kubeadm、kubelet 和 …

4大遥感软件!遥感影像解译!ArcGIS+ENVI+Erdas+eCognition

包含ArcGISENVIErdaseCognition 4大软件4个课程的遥感影像大综合&#xff0c;一个课程套餐让你学遍常用的遥感影像处分析等。 课后答疑 学习群答疑 实战驱动 课件、课程操作数据 福利数据包 课程概述 总共146&#xff08;18454538&#xff09;课时 点下如下课程卡学习&…

5.07 Pneumonia Detection in Chest X-Rays using Neural Networks

肺炎诊断是一个耗时的过程&#xff0c;需要高技能的专业人员分析胸部X光片chest X-ray (CXR)&#xff0c;并通过临床病史、生命体征和实验室检查确认诊断。 它可以帮助医生确定肺部感染的程度和位置。呼吸道疾病在 X 光片上表现为一处膨胀的不透明区域。然而&#xff0c;由于不…

浅谈操作系统中的重要概念——线程(3)——设计模式

文章目录 一、什么是设计模式&#xff1f;二、单例模式2.1、饿汉模式2.2、懒汉模式2.3、多线程情况下调用 饿汉模式与懒汉模式 谁是安全的&#xff1f;&#xff1f;&#xff08;重点&#xff09; 三、工厂模式3.1、什么是工厂模式&#xff1f;3.1.1、构造方法存在的缺陷3.1.1.1…

初步了解Kubernetes

目录 1. K8S概述 1.1 K8S是什么 1.2 作用 1.3 由来 1.4 含义 1.5 相关网站 2. 为什么要用K8S 3. K8S解决的问题 4. K8S的特性 5. Kubernetes集群架构与组件 6. 核心组件 6.1 Master组件 6.1.1 Kube-apiserver 6.1.2 Kube-controller-manager 6.1.3 kube-schedul…

基于springboot实现智慧图书管理系统项目【项目源码+论文说明】

基于springboot实现智慧图书管理系统演示 摘要 如今社会上各行各业&#xff0c;都在用属于自己专用的软件来进行工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。互联网的发展&#xff0c;离不开一些新的技术&#xff0c;而新技术的产生往往是为…

企业数据有什么价值?

在当下的数字经济时代&#xff0c;数据已上升为国家重要的基础性战略资源&#xff0c;加快建设数字中国、网络强国这一蓝图的实现&#xff0c;离不开数据要素的支撑。数据作为新型生产要素&#xff0c;具有非消耗性、非竞争性等特征&#xff0c;为突破传统生产要素的增长约束提…

SolidWorks2024 正版软件报价

随着科技的飞速发展&#xff0c;三维设计软件在制造业、工程领域的应用越来越广泛。SolidWorks作为一款三维CAD设计软件&#xff0c;其每一代的更新都受到广大用户的热烈关注。今日&#xff0c;我们将深入探讨SolidWorks 2024正版软件的报价及其所蕴含的功能价值。 首先&#…

光检测器——光纤通信学习笔记七

光检测器 光检测器的基本介绍 作用&#xff1a;把接受到的光信号转换成电信号 光接收器的灵敏度、光源的发光功率和光纤的损耗三者决定了光纤通信的传输距离&#xff1b; 光电二极管 光电转换的基本原理 之前提到&#xff0c;PN结由于内部载流子的扩散运动形成了内部电场&…

uni-app(五):原生插件打包并使用(Android)

原生插件打包并使用 解决Gradle不显示命令问题解决方法 运行打包查看打包好的包引入到uni-app项目中编写配置文件TestModuleTestComponent 制作基座并运行 解决Gradle不显示命令问题 解决方法 运行打包 查看打包好的包 引入到uni-app项目中 编写配置文件 TestModule {"n…

postgresql主从复制

用vmware 搭建的两台虚拟机 操作系统&#xff1a;Ubuntu 24.04 Server版 数据库&#xff1a;postgresql 16.2 主库&#xff1a;192.168.2.11 从库&#xff1a;192.168.2.12 如果遇到网络无法上网&#xff0c;可参考一下 Vmware 搭建的Ubuntu 24.04 网络配置-CSDN博客 1.两…

错误处理机制——vba(vb.net)

程序出现错误时可采用如下错误处理机制&#xff1a;出错时跳到标签处&#xff0c;判断错误类型修正错误&#xff0c;重新返回正确标签处&#xff0c;继续运行程序。 代码如下&#xff1a; Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click…