【Go学习】-02-1-标准库:fmt、os、time

【Go学习】-02-1-标准库:fmt、os、time

  • 1 fmt标准库
    • 1.1 输出
      • 1.1.1 fmt.Print
      • 1.1.2 格式化占位符
        • 1.1.2.1 通用占位符
        • 1.1.2.2 布尔型
        • 1.1.2.3 整型
        • 1.1.2.4 浮点数与复数
        • 1.1.2.5 字符串和[]byte
        • 1.1.2.6 指针
        • 1.1.2.7 宽度标识符
        • 1.1.2.8 其他flag
      • 1.1.3 Fprint
      • 1.1.4 Sprint
      • 1.1.5 Errorf
    • 1.2 输入
      • 1.2.1 fmt.Scan
      • 1.2.2 fmt.Scanf
      • 1.2.3 fmt.Scanln
      • 1.2.4 fmt.Fsanf
  • 2 os标准库
    • 2.1 权限说明
    • 2.2 os.Create
    • 2.3 os.Mkdir
    • 2.4 os.MkdirAll
    • 2.5 os.Remove
    • 2.6 os.RemoveAll
    • 2.7 os.Getwd
    • 2.8 os.Chdir
    • 2.9 os.TempDir
    • 2.10 os.Rename
    • 2.11 os.Chmod
    • 2.12 os.Chown
    • 2.13 文件
      • 2.13.1 文件读取
      • 2.13.2 文件写
    • 2.14 进程相关
      • 2.14.1 Signal
    • 2.15 环境相关
  • 3 time标准库
    • 3.1 Time类型
    • 3.2 时间戳
    • 3.3 Parse解析时间
    • 3.4 格式化时间
    • 3.5 time.Unix()
    • 3.6 时间间隔
    • 3.7 时间计算
      • 3.7.1 Add
      • 3.7.2 Sub
      • 3.7.3 Equal
      • 3.7.4 Before
      • 3.7.5 After
    • 3.8 定时器


1 fmt标准库

go版本:1.18.1

主要分为向外输出内容和获取输入内容两大部分

1.1 输出

1.1.1 fmt.Print

print 有三个相关的函数:

func Print(a ...any) (n int, err error) {return Fprint(os.Stdout, a...)
}
func Println(a ...any) (n int, err error) {return Fprintln(os.Stdout, a...)
}
func Printf(format string, a ...any) (n int, err error) {return Fprintf(os.Stdout, format, a...)
}

可以看到,最终调用的都是Fprintf,os.Stdout代表标准输出,即控制台输出

示例:

package mainimport ("fmt""testing"
)func TestPrint(t *testing.T) {fmt.Print("我是控制台打印,我不换行 可以自己控制换行\n")
}
func TestPrintln(t *testing.T) {fmt.Println("我是控制台打印,我换行")
}
func TestPrintf(t *testing.T) {fmt.Printf("我是控制台打印,%s \n", "这是格式化占位符信息,可以自己控制换行")
}
我是控制台打印,我不换行 可以自己控制换行
我是控制台打印,我换行
我是控制台打印,这是格式化占位符信息,可以自己控制换行

1.1.2 格式化占位符

1.1.2.1 通用占位符
占位符说明
%v值的默认格式表示
%+v类似%v,但输出结构体时会添加字段名
%#v值的Go语法表示
%T打印值的类型
%%百分号
type User struct {Id int64
}func TestPrintf1(t *testing.T) {user := &User{Id: 1}fmt.Printf("%v\n", user)fmt.Printf("%+v\n", user)fmt.Printf("%#v\n", user)fmt.Printf("%T\n", user)fmt.Printf("%%\n")
}
func main() {TestPrintf1(nil)
}
&{1}
&{Id:1}
&main.User{Id:1}
*main.User
%
1.1.2.2 布尔型
占位符说明
%ttrue或false
func TestPrintf2(t *testing.T) {fmt.Printf("%t\n", true)
}
1.1.2.3 整型
占位符说明
%b表示为二进制
%c该值对应的unicode码值
%d表示为十进制
%o表示为八进制
%x表示为十六进制,使用a-f
%X表示为十六进制,使用A-F
%U表示为Unicode格式:U+1234,等价于”U+%04X”
%q该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示

在这里插入图片描述

func TestPrintf3(t *testing.T) {n := 180fmt.Printf("%b\n", n)fmt.Printf("%c\n", n)fmt.Printf("%d\n", n)fmt.Printf("%o\n", n)fmt.Printf("%x\n", n)fmt.Printf("%X\n", n)fmt.Printf("%U\n", n)a := 97fmt.Printf("%q\n", a)fmt.Printf("%q\n", 0x4E2D)
}
10110100
´
180
264
b4
B4
U+00B4
'a'
'中'
1.1.2.4 浮点数与复数
占位符说明
%b无小数部分、二进制指数的科学计数法,如-123456p-78
%e科学计数法,如-1234.456e+78
%E科学计数法,如-1234.456E+78
%f有小数部分但无指数部分,如123.456
%F等价于%f
%g根据实际情况采用%e或%f格式(以获得更简洁、准确的输出)
%G根据实际情况采用%E或%F格式(以获得更简洁、准确的输出)
func TestPrintf4(t *testing.T) {f := 18.54fmt.Printf("%b\n", f)fmt.Printf("%e\n", f)fmt.Printf("%E\n", f)fmt.Printf("%f\n", f)fmt.Printf("%F\n", f)fmt.Printf("%g\n", f)fmt.Printf("%G\n", f)
}
5218546068215562p-48
1.854000e+01
1.854000E+01
18.540000
18.540000
18.54
18.54
1.1.2.5 字符串和[]byte
占位符说明
%s直接输出字符串或者[]byte
%q该值对应的双引号括起来的go语法字符串字面值,必要时会采用安全的转义表示
%x每个字节用两字符十六进制数表示(使用a-f
%X每个字节用两字符十六进制数表示(使用A-F)
func TestPrintf5(t *testing.T) {s := "我是bblb"b := []byte{65, 66, 67}fmt.Printf("%s\n", s)fmt.Printf("%s\n", b)fmt.Printf("%q\n", s)fmt.Printf("%d\n", b)fmt.Printf("%q\n", b)fmt.Printf("%x\n", s)fmt.Printf("%X\n", s)fmt.Printf("%x\n", b)fmt.Printf("%X\n", b)
}
我是bblb
ABC
"我是bblb"
[65 66 67]
"ABC"
e68891e698af62626c62
E68891E698AF62626C62
414243
414243
1.1.2.6 指针
占位符说明
%p表示为十六进制,并加上前导的0x
func TestPrintf6(t *testing.T) {user := &User{Id: 1}fmt.Printf("%p\n", user)
}
0xc00000a0f8
1.1.2.7 宽度标识符
占位符说明
%10.2小数点前表示宽度,小数点后表示精度

宽度通过一个紧跟在百分号后面的十进制数指定,如果未指定宽度,则表示值时除必需之外不作填充。

精度通过(可选的)宽度后跟点号后跟的十进制数指定。如果未指定精度,会使用默认精度;如果点号后没有跟数字,表示精度为0。

占位符说明
%f默认宽度,默认精度
%10f宽度9,默认精度
%.2f默认宽度,精度2
%10.2f宽度9,精度2
%10.f宽度9,精度0
func TestPrintf6(t *testing.T) {n := 13.14fmt.Printf("%f\n", n)fmt.Printf("%10f\n", n)fmt.Printf("%10s\n", "我是字符串")fmt.Printf("%.2f\n", n)fmt.Printf("%10.2f\n", n)fmt.Printf("%10.f\n", n)
}
13.14000013.140000我是字符串
13.1413.1413
1.1.2.8 其他flag
占位符说明
+总是输出数值的正负号;对%q(%+q)会生成全部是ASCII字符的输出(通过转义);
空格对数值,正数前加空格而负数前加负号;对字符串采用%x或%X时(% x或% X)会给各打印的字节之间加空格
-在输出右边填充空白而不是默认的左边(即从默认的右对齐切换为左对齐);
#八进制数前加0(%#o),十六进制数前加0x(%#x)或0X(%#X),指针去掉前面的0x(%#p)对%q(%#q),对%U(%#U)会输出空格和单引号括起来的go字面值;
0使用0而不是空格填充,对于数值类型会把填充的0放在正负号后面;
func TestPrintf7(t *testing.T) {s := "我是字符串"fmt.Printf("%  d\n", 10)fmt.Printf("%s\n", s)fmt.Printf("%10s\n", s)fmt.Printf("%-10s\n", s)fmt.Printf("%10.2f\n", 10.14)fmt.Printf("%-10.2f\n", 10.14)fmt.Printf("%010s\n", s)
}
 10
我是字符串我是字符串
我是字符串10.14
10.14
00000我是字符串

1.1.3 Fprint

将内容输出到一个io.Writer接口类型的变量w中。

func Fprint(w io.Writer, a ...any) (n int, err error) {p := newPrinter()p.doPrint(a)n, err = w.Write(p.buf)p.free()return
}
func Fprintf(w io.Writer, format string, a ...any) (n int, err error) {p := newPrinter()p.doPrintf(format, a)n, err = w.Write(p.buf)p.free()return
}
func Fprintln(w io.Writer, a ...any) (n int, err error) {p := newPrinter()p.doPrintln(a)n, err = w.Write(p.buf)p.free()return
}

n是写入的字节数量,err是返回的错误

一般用在写文件中。

func TestFPrint(t *testing.T) {fmt.Fprintln(os.Stdout, "向标准输出写入字符串")
}
//0表示8进制 644表示权限 os.FileMode(0777).String()进行打印//- rwx rwx rwx -表示普通文件//r表示可读//w表示可写//x表示可执行//第1位:文件属性,一般常用的是"-",表示是普通文件;"d"表示是一个目录。//第2~4位:文件所有者的权限rwx (可读/可写/可执行)。//第5~7位:文件所属用户组的权限rwx (可读/可写/可执行)。//第8~10位:其他人的权限rwx (可读/可写/可执行)。//在golang中,可以使用os.FileMode(perm).String()来查看权限标识://os.FileMode(0777).String() //返回 -rwxrwxrwx  111 111 111//os.FileMode(0666).String() //返回 -rw-rw-rw-  110 110 110//os.FileMode(0644).String() //返回 -rw-r--r-- //0777表示:创建了一个普通文件,所有人拥有所有的读、写、执行权限//0666表示:创建了一个普通文件,所有人拥有对该文件的读、写权限,但是都不可执行//0644表示:创建了一个普通文件,文件所有者对该文件有读写权限,用户组和其他人只有读权限,都没有执行权限s := os.FileMode(0777).String()fmt.Println(s)
func TestFPrint1(t *testing.T) {file, _ := os.OpenFile("test.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)fmt.Fprintln(file, "追加写入")file.Close()
}
package mainimport ("fmt""net/http"
)func main() {//输入http.ListenAndServe(":8088", &MyHandler{})
}type MyHandler struct {
}func (*MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {fmt.Fprintln(w, "我是http返回的信息")
}

1.1.4 Sprint

把传入的数据生成并返回一个字符串

func Sprint(a ...any) string {p := newPrinter()p.doPrint(a)s := string(p.buf)p.free()return s
}
func Sprintf(format string, a ...any) string {p := newPrinter()p.doPrintf(format, a)s := string(p.buf)p.free()return s
}
func Sprintln(a ...any) string {p := newPrinter()p.doPrintln(a)s := string(p.buf)p.free()return s
}
func TestSPrint(t *testing.T) {s1 := fmt.Sprint("张三\n")name := "张三"age := 18s2 := fmt.Sprintf("name:%s,age:%d\n", name, age)s3 := fmt.Sprintln("张三")fmt.Print(s1)fmt.Print(s2)fmt.Print(s3)
}
张三
name:张三,age:18
张三

1.1.5 Errorf

根据format参数生成格式化字符串并返回一个包含该字符串的错误

func Errorf(format string, a ...any) error
func TestErrorf(t *testing.T) {err := fmt.Errorf("用户名格式不正确:%s", "@#¥哈哈")if err != nil {panic(err)}
}

1.2 输入

1.2.1 fmt.Scan

定义:

func Scan(a ...any) (n int, err error) {return Fscan(os.Stdin, a...)
}

含义:

从标准输入扫描文本,读取由空白符分隔的值保存到传递给本函数的参数中,换行符视为空白符

返回值:

本函数返回成功扫描的数据个数(n)和遇到的任何错误(error)

func main() {//空格 换行输入都可以var (name    stringage     intmarried bool)fmt.Scan(&name, &age, &married)fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
}
bblb 23 false
扫描结果 name:bblb age:23 married:false 

1.2.2 fmt.Scanf

func Scanf(format string, a ...any) (n int, err error) {return Fscanf(os.Stdin, format, a...)
}

实际使用的是Fscanf

以format定义的格式来进行输入

func main() {var (name    stringage     intmarried bool)fmt.Scanf("1:%s 2:%d 3:%t", &name, &age, &married)fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
}
1:bblb 2:23 3:false
扫描结果 name:bblb age:23 married:false 

1.2.3 fmt.Scanln

func Scanln(a ...any) (n int, err error) {return Fscanln(os.Stdin, a...)
}
func main() {var (name    stringage     intmarried bool)fmt.Scanln(&name, &age, &married)fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
}

遇到回车就结束扫描

1.2.4 fmt.Fsanf

func Fscanf(r io.Reader, format string, a ...any) (n int, err error) {s, old := newScanState(r, false, false)n, err = s.doScanf(format, a)s.free(old)return
}
func Fscan(r io.Reader, a ...any) (n int, err error) {s, old := newScanState(r, true, false)n, err = s.doScan(a)s.free(old)return
}
func Fscanln(r io.Reader, a ...any) (n int, err error) {s, old := newScanState(r, false, true)n, err = s.doScan(a)s.free(old)return
}

将内容从一个io.Reader接口类型的变量r中读取出来,将连续的以空格分隔的值存储到由格式确定的连续的参数中

  • **r io.Reader:**此参数包含扫描的指定文本。
  • **format string:**此参数包含用于接收元素的不同格式。
  • **a …any:**此参数是每个元素的指定变量。

**返回值:**它返回成功解析的项目数和错误

func main() {var (name    stringage     intmarried bool)r := strings.NewReader("10 false 张三")n, err := fmt.Fscanf(r, "%d %t %s", &age, &married, &name)if err != nil {fmt.Fprintf(os.Stderr, "Fscanf:%v\n", err)}fmt.Println(name, age, married)fmt.Println(n)
}

2 os标准库

os包提供了操作系统函数,但和操作系统无关。

os包的接口规定为在所有操作系统中都是一致的。

设计为Unix风格的。

2.1 权限说明

os标准库有大量的文件操作,在创建文件等操作中,需要指的perm。

在go语言中perm是一个uint32类型

在go语言中一般使用0777这样的形式进行表示。

  • 0代表是8进制

  • 777 是 - rwx rwx rwx的形式计算得出

权限项文件类型执行执行执行
字符表示(d|l|c|s|p)rwxrwxrwx
数字表示421421421
权限分配文件所有者文件所有者文件所有者文件所属组用户文件所属组用户文件所属组用户其他用户其他用户其他用户

第一位:

- : 代表这是一个普通文件(regular)
d:目录文件(directory)
l : 链接文件(link)
b: 块设备文件(block)
c: 字符设备文件(character)
s : 套接字文件(socket)
p: 管道文件(pipe)

一共有三组rwx

  • 第一组:该文件拥有者的权限
  • 第二组:该文件拥有者所在组的其他成员对该文件的操作权限
  • 第三组:其他用户组的成员对该文件的操作权限

计算过程如下:

rwxrwxrwx
111111111
777

go中的FileMode定义

type FileMode uint32

FileMode代表文件的模式和权限位。这些字位在所有的操作系统都有相同的含义,因此文件的信息可以在不同的操作系统之间安全的移植。不是所有的位都能用于所有的系统,唯一共有的是用于表示目录的ModeDir位。

const (// 单字符是被String方法用于格式化的属性缩写。ModeDir        FileMode = 1 << (32 - 1 - iota) // d: 目录ModeAppend                                     // a: 只能写入,且只能写入到末尾ModeExclusive                                  // l: 用于执行ModeTemporary                                  // T: 临时文件(非备份文件)ModeSymlink                                    // L: 符号链接(不是快捷方式文件)ModeDevice                                     // D: 设备ModeNamedPipe                                  // p: 命名管道(FIFO)ModeSocket                                     // S: Unix域socketModeSetuid                                     // u: 表示文件具有其创建者用户id权限ModeSetgid                                     // g: 表示文件具有其创建者组id的权限ModeCharDevice                                 // c: 字符设备,需已设置ModeDeviceModeSticky                                     // t: 只有root/创建者能删除/移动文件// 覆盖所有类型位(用于通过&获取类型位),对普通文件,所有这些位都不应被设置ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDeviceModePerm FileMode = 0777 // 覆盖所有Unix权限位(用于通过&获取类型位)
)

这些被定义的位是FileMode最重要的位。另外9个不重要的位为标准Unix rwxrwxrwx权限(任何人都可读、写、运行)。这些(重要)位的值应被视为公共API的一部分,可能会用于线路协议或硬盘标识:它们不能被修改,但可以添加新的位。

2.2 os.Create

func Create(name string) (file *File, err error)

Create采用模式0666(任何人都可读写,不可执行)创建一个名为name的文件,如果文件已存在会截断它(为空文件)。如果成功,返回的文件对象可用于I/O;对应的文件描述符具有O_RDWR模式。

如果出错,错误底层类型是*PathError

// 创建文件
func createFile() {f, err := os.Create("test.txt")if err != nil {fmt.Printf("err: %v\n", err)} else {fmt.Printf("f: %v\n", f)}
}

2.3 os.Mkdir

创建单个目录

func Mkdir(name string, perm FileMode) error {}
func mkdir() {err := os.Mkdir("ms", os.ModePerm)if err != nil {fmt.Printf("err: %v\n", err)} 
}

2.4 os.MkdirAll

创建多级目录

func MkdirAll(path string, perm FileMode) error {}
func mkdirAll() {err := os.MkdirAll("ms/one/two", os.ModePerm)if err != nil {fmt.Printf("err: %v\n", err)}
}

2.5 os.Remove

删除一个空的目录或一个文件

func Remove(name string) error {}
func removeFile() {err := os.Remove("test.txt")if err != nil {fmt.Printf("err: %v\n", err)}
}
func removeDir() {err := os.Remove("ms/one/two")if err != nil {fmt.Printf("err: %v\n", err)}
}

2.6 os.RemoveAll

强制删除目录以及目录汇中的文件

func RemoveAll(path string) error {return removeAll(path)
}
func removeAllDir() {err := os.RemoveAll("ms")if err != nil {fmt.Printf("err: %v\n", err)}
}

2.7 os.Getwd

获得工作目录

func Getwd() (dir string, err error) {}
func getWd() {dir, err := os.Getwd()if err != nil {fmt.Printf("err: %v\n", err)} else {fmt.Printf("dir: %v\n", dir)}
}

2.8 os.Chdir

修改工作目录

//改变工作目录到f,其中f必须为一个目录,否则便会报错
func (f *File) Chdir() error
func chDir() {err := os.Chdir("d:/go/project")if err != nil {fmt.Printf("err: %v\n", err)}fmt.Println(os.Getwd())
}

2.9 os.TempDir

获得临时目录

func TempDir() string {return tempDir()
}
func tempDir() {s := os.TempDir()fmt.Printf("s: %v\n", s)
}

2.10 os.Rename

重命名文件

func Rename(oldpath, newpath string) error {return rename(oldpath, newpath)
}
func renameFile() {err := os.Rename("test.txt", "test2.txt")if err != nil {fmt.Printf("err: %v\n", err)}
}
func renameDir() {err := os.Rename("ms", "ms1")if err != nil {fmt.Printf("err: %v\n", err)}
}

2.11 os.Chmod

修改文件权限

func Chmod(name string, mode FileMode) error { return chmod(name, mode) 
}
func chmod() {err := os.Chmod("test2.txt", 0111)if err != nil {fmt.Printf("err: %v\n", err)}
}

打包linux测试

SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build main.go

2.12 os.Chown

修改文件所有者

func Chown(name string, uid, gid int) error {}

cat /etc/passwd 查看uid和gid

func chown() {err := os.Chown("test2.txt", 10, 10)if err != nil {fmt.Printf("err: %v\n", err)}
}

2.13 文件

打开模式

const (O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件O_RDWR   int = syscall.O_RDWR   // 读写模式打开文件O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部O_CREATE int = syscall.O_CREAT  // 如果不存在将创建一个新文件O_EXCL   int = syscall.O_EXCL   // 和O_CREATE配合使用,文件必须不存在O_SYNC   int = syscall.O_SYNC   // 打开文件用于同步I/OO_TRUNC  int = syscall.O_TRUNC  // 如果可能,打开时清空文件
)
 // 创建一个空文件,注意当文件已经存在时,会直接覆盖掉原文件,不会报错
func Create(name string) (file *File, err error)
// 打开一个文件,注意打开的文件只能读,不能写
func Open(name string) (file *File, err error) 
// 以指定的权限打开文件
func OpenFile(name string, flag int, perm FileMode) (file *File, err error) 
// 关闭文件,关闭后不可读写
func (f *File) Close() error 

其实os.Create 等价于:OpenFile(name, O_RDWF|O_CREATE|O_TRUNK, 0666)

func openClose() {f, err := os.OpenFile("test2.txt", os.O_RDWR|os.O_CREATE, 0755)if err != nil {panic(err)}fmt.Println("file name : ", f.Name())defer f.Close()}

2.13.1 文件读取

// 获取文件的信息,里面有文件的名称,大小,修改时间等
func (f *File) Stat() (fi FileInfo, err error) 
// 从文件中一次性读取b大小的数据,当读到文件结尾时,返回一个EOF错误
func (f *File) Read(b []byte) (n int, err error) 
// 从文件中指定的位置(off)一次性读取b大小的数据
func (f *File) ReadAt(b []byte, off int64) (n int, err error) 
// 读取目录并返回排好序的文件以及子目录名切片
func ReadDir(name string) ([]DirEntry, error) 
//Seek设置下一次读/写的位置。offset为相对偏移量,而whence决定相对位置:0为相对文件开头,1为相对当前位置,2为相对文件结尾。它返回新的偏移量(相对开头)和可能的错误。
func (f *File) Seek(offset int64, whence int) (ret int64, err error)
type FileInfo interface {Name() string       // 文件的名字(不含扩展名)Size() int64        // 普通文件返回值表示其大小;其他文件的返回值含义各系统不同Mode() FileMode     // 文件的模式位ModTime() time.Time // 文件的修改时间IsDir() bool        // 等价于Mode().IsDir()Sys() interface{}   // 底层数据来源(可以返回nil)
}func fileStat() {f, err := os.OpenFile("test2.txt", os.O_RDWR|os.O_CREATE, 0755)if err != nil {panic(err)}defer f.Close()fileInfo, err := f.Stat()if err != nil {panic(err)}fmt.Printf("file info : %#v", fileInfo)
}
func fileRead() {f, err := os.OpenFile("test2.txt", os.O_RDWR|os.O_CREATE, 0755)if err != nil {panic(err)}defer f.Close()var body []bytefor {buf := make([]byte, 4)n, err := f.Read(buf)if err == io.EOF {//读完了break}fmt.Printf("读到的位置:%d \n", n)body = append(body, buf[:n]...)}fmt.Printf("内容:%s \n", body)
}
func fileReadAt() {f, err := os.OpenFile("test2.txt", os.O_RDWR|os.O_CREATE, 0755)if err != nil {panic(err)}defer f.Close()buf := make([]byte, 5)n, err := f.ReadAt(buf, 6)fmt.Printf("内容:%s \n", buf[:n])
}
func fileReadDir() {f, err := os.Open("ms1")if err != nil {panic(err)}defer f.Close()//-1代表所有dirs, err := f.ReadDir(-1)if err != nil {panic(err)}for _, v := range dirs {fmt.Println("is dir:", v.IsDir())fmt.Println("dir name :", v.Name())}
}
func fileSeek() {f, err := os.OpenFile("test2.txt", os.O_RDWR|os.O_CREATE, 0755)if err != nil {panic(err)}defer f.Close()f.Seek(3, 0)buf := make([]byte, 10)n, _ := f.Read(buf)fmt.Printf("读取内容:%s\n", buf[:n])
}

2.13.2 文件写

//Write向文件中写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。
func (f *File) Write(b []byte) (n int, err error)
//WriteString类似Write,但接受一个字符串参数。
func (f *File) WriteString(s string) (ret int, err error)
//WriteAt在指定的位置(相对于文件开始位置)写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。
func (f *File) WriteAt(b []byte, off int64) (n int, err error)
func fileWrite() {f, err := os.OpenFile("test2.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0755)if err != nil {panic(err)}defer f.Close()f.Write([]byte("hello golang~\n"))f.WriteString("hello golang~\n")
}
func fileWriteAt() {f, err := os.OpenFile("test2.txt", os.O_RDWR|os.O_CREATE, 0755)if err != nil {panic(err)}defer f.Close()_, err = f.WriteAt([]byte(" insert content~\n"), 5)fmt.Println(err)
}

2.14 进程相关

// 让当前程序以给出的状态码(code)退出。一般来说,状态码0表示成功,非0表示出错。程序会立刻终止,defer的函数不会被执行。
func Exit(code int) 
// 获取调用者的用户id
func Getuid() int 
// 获取调用者的有效用户id
func Geteuid() int // 获取调用者的组id
func Getgid() int
// 获取调用者的有效组id
func Getegid() int 
// 获取调用者所在的所有组的组id
func Getgroups() ([]int, error) 
// 获取调用者所在进程的进程id
func Getpid() int 
// 获取调用者所在进程的父进程的进程id
func Getppid() int 
func osInfo() {// 获得当前正在运行的进程idfmt.Println("---------")fmt.Printf("os.Getpid(): %v\n", os.Getpid())// 父idfmt.Printf("os.Getppid(): %v\n", os.Getppid())// 设置新进程的属性attr := &os.ProcAttr{// files指定新进程继承的活动文件对象// 前三个分别为,标准输入、标准输出、标准错误输出Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},// 新进程的环境变量Env: os.Environ(),}// 开始一个新进程p, err := os.StartProcess("c:\\windows\\system32\\notepad.exe", []string{"c:\\windows\\system32\\notepad.exe", "d:\\test.txt"}, attr)if err != nil {fmt.Println(err)}fmt.Println(p)fmt.Println("进程ID:", p.Pid)// 通过进程ID查找进程p2, _ := os.FindProcess(p.Pid)fmt.Println(p2)// 等待10秒,执行函数time.AfterFunc(time.Second*10, func() {// 向p进程发出退出信号p.Signal(os.Kill)})// 等待进程p的退出,返回进程状态ps, _ := p.Wait()fmt.Println(ps.String())
}

type Signal

type Signal interface {String() stringSignal() // 用来区分其他实现了Stringer接口的类型
}

Signal代表一个操作系统信号。一般其底层实现是依赖于操作系统的:在Unix中,它是syscall.Signal类型。

var (Interrupt Signal = syscall.SIGINTKill      Signal = syscall.SIGKILL
)

仅有的肯定会被所有操作系统提供的信号,Interrupt(中断信号)和Kill(强制退出信号)。

var (ErrInvalid    = errors.New("invalid argument")ErrPermission = errors.New("permission denied")ErrExist      = errors.New("file already exists")ErrNotExist   = errors.New("file does not exist")
)

一些可移植的、共有的系统调用错误。

var (Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)

Stdin、Stdout和Stderr是指向标准输入、标准输出、标准错误输出的文件描述符。

var Args []string

Args保管了命令行参数,第一个是程序名。

2.14.1 Signal

func main() {go a()go b()ch := make(chan os.Signal)signal.Notify(ch, os.Kill, os.Interrupt)c := <-chlog.Println(c)
}func b() {fmt.Println("b")
}func a() {fmt.Println("a")
}

2.15 环境相关

// 获取主机名
func Hostname() (name string, err error) 
// 获取某个环境变量
func Getenv(key string) string  
// 设置一个环境变量,失败返回错误,经测试当前设置的环境变量只在 当前进程有效(当前进程衍生的所有的go程都可以拿到,子go程与父go程的环境变量可以互相获取);进程退出消失
func Setenv(key, value string) error 
// 删除当前程序已有的所有环境变量。不会影响当前电脑系统的环境变量,这些环境变量都是对当前go程序而言的
func Clearenv() 
func osEnv() {// 获得所有环境变量s := os.Environ()fmt.Printf("s: %v\n", s)// 获得某个环境变量s2 := os.Getenv("GOPATH")fmt.Printf("s2: %v\n", s2)// 设置环境变量os.Setenv("env1", "env1")s2 = os.Getenv("aaa")fmt.Printf("s2: %v\n", s2)fmt.Println("--------------")// 查找s3, b := os.LookupEnv("env1")fmt.Printf("b: %v\n", b)fmt.Printf("s3: %v\n", s3)// 清空环境变量# // os.Clearenv()
}

3 time标准库

时间在日常编程中使用非常多。time标准库中日历的计算采用的是公历

3.1 Time类型

  • Time代表一个纳秒精度的时间点。

  • 程序中应使用Time类型值来保存和传递时间,而不能用指针。就是说,表示时间的变量和字段,应为time.Time类型,而不是*time.Time.类型。

  • 一个Time类型值可以被多个goroutine同时使用。

  • 时间点可以使用BeforeAfterEqual方法进行比较。

  • Sub方法让两个时间点相减,生成一个Duration类型值(代表时间段)。

  • Add方法给一个时间点加上一个时间段,生成一个新的Time类型时间点。

  • Time零值代表时间点January 1, year 1, 00:00:00.000000000 UTC。因为本时间点一般不会出现在使用中,IsZero方法提供了检验时间是否显式初始化的一个简单途径。

  • 每一个时间都具有一个地点信息(及对应地点的时区信息),当计算时间的表示格式时,如FormatHourYear等方法,都会考虑该信息。

  • LocalUTCIn方法返回一个指定时区(但指向同一时间点)的Time。修改地点/时区信息只是会改变其表示;不会修改被表示的时间点,因此也不会影响其计算。

func timeDemo() {now := time.Now() //获取当前时间fmt.Printf("current time:%v\n", now)year := now.Year()     //年month := now.Month()   //月day := now.Day()       //日hour := now.Hour()     //小时minute := now.Minute() //分钟second := now.Second() //秒//02d输出的整数不足两位 用0补足fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second)
}
current time:2025-01-07 15:17:37.3931982 +0800 CST m=+0.000503101

3.2 时间戳

时间戳是自1970年1月1日0时0分0秒至当前时间的总毫秒数。它也被称为Unix时间戳(UnixTimestamp)。

这里指的是UTC时间,比北京时间晚8个小时。

func timestampDemo() {now := time.Now()            //获取当前时间timestamp1 := now.Unix()     //时间戳timestamp2 := now.UnixNano() //纳秒时间戳fmt.Printf("current timestamp1:%v\n", timestamp1)fmt.Printf("current timestamp2:%v\n", timestamp2)
}
current timestamp1:1736234366
current timestamp2:1736234366304093900

3.3 Parse解析时间

func Parse(layout, value string) (Time, error)

解析一个格式化的时间字符串并返回它代表的时间,如果缺少表示时区的信息,Parse会将时区设置为UTC。

func ParseInLocation(layout, value string, loc *Location) (Time, error)

ParseInLocation类似Parse但有两个重要的不同之处。第一,当缺少时区信息时,Parse将时间解释为UTC时间,而ParseInLocation将返回值的Location设置为loc;第二,当时间字符串提供了时区偏移量信息时,Parse会尝试去匹配本地时区,而ParseInLocation会去匹配loc。

layout的时间必须是"2006-01-02 15:04:05"这个时间,当然格式不一定是这个,时间一定得是,这是go诞生的时间

func timeParse() {t, err := time.Parse("2006-01-02 15:04:05", "2022-07-28 18:06:00")if err != nil {panic(err)}fmt.Println(t)now := time.Now()fmt.Println(now)// 加载时区loc, err := time.LoadLocation("Asia/Shanghai")if err != nil {fmt.Println(err)return}// 按照指定时区和指定格式解析字符串时间timeObj, err := time.ParseInLocation("2006/01/02 15:04:05", now.Format("2006/01/02 15:04:05"), loc)if err != nil {fmt.Println(err)return}fmt.Println(timeObj)}
2025-01-07 18:06:00 +0000 UTC
2025-01-07 15:20:56.4819929 +0800 CST m=+0.000503901
2025-01-07 15:20:56 +0800 CST

3.4 格式化时间

func (t Time) Format(layout string) string

Format根据layout指定的格式返回t代表的时间点的格式化文本表示。

func timeFormat() {now := time.Now()// 格式化的模板为Go的出生时间2006年1月2号15点04分05秒// 24小时制fmt.Println(now.Format("2006-01-02 15:04:05.000"))// 12小时制fmt.Println(now.Format("2006-01-02 03:04:05"))fmt.Println(now.Format("2006/01/02 15:04"))fmt.Println(now.Format("15:04 2006/01/02"))fmt.Println(now.Format("2006/01/02"))
}
2025-01-07 16:03:25.198
2025-01-07 04:03:25
2025/01/07 16:03
16:03 2025/01/07
2025/01/07

3.5 time.Unix()

func Unix(sec int64, nsec int64) Time

Unix创建一个本地时间,对应sec和nsec表示的Unix时间(从January 1, 1970 UTC至该时间的秒数和纳秒数)。

nsec的值在[0, 999999999]范围内是合法的。

func timestampDemo2(timestamp int64) {timeObj := time.Unix(timestamp, 0) //将时间戳转为时间格式fmt.Println(timeObj)year := timeObj.Year()     //年month := timeObj.Month()   //月day := timeObj.Day()       //日hour := timeObj.Hour()     //小时minute := timeObj.Minute() //分钟second := timeObj.Second() //秒fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second)
}
timestampDemo2(1609430400)
2021-01-01 00:00:00 +0800 CST
2021-01-01 00:00:00

3.6 时间间隔

time.Duration是time包定义的一个类型,它代表两个时间点之间经过的时间,以纳秒为单位。time.Duration表示一段时间间隔,可表示的最长时间段大约290年。

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

const (Nanosecond  Duration = 1Microsecond          = 1000 * NanosecondMillisecond          = 1000 * MicrosecondSecond               = 1000 * MillisecondMinute               = 60 * SecondHour                 = 60 * Minute
)

例如:time.Duration表示1纳秒,time.Second表示1秒。

3.7 时间计算

3.7.1 Add

func (t Time) Add(d Duration) Time

Add返回时间点t+d。

func main() {now := time.Now()later := now.Add(time.Hour) // 当前时间加1小时后的时间fmt.Println(later)
}

3.7.2 Sub

求两个时间之间的差值

    func (t Time) Sub(u Time) Duration

返回一个时间段t-u。如果结果超出了Duration可以表示的最大值/最小值,将返回最大值/最小值。

要获取时间点t-d(d为Duration),可以使用t.Add(-d)。

func main() {now := time.Now()later := now.Add(time.Hour) // 当前时间加1小时后的时间ret := later.Sub(now)fmt.Println(ret)
}

3.7.3 Equal

func (t Time) Equal(u Time) bool

判断两个时间是否相同,会考虑时区的影响,因此不同时区标准的时间也可以正确比较。

本方法和用t==u不同,这种方法还会比较地点和时区信息。

3.7.4 Before

func (t Time) Before(u Time) bool

如果t代表的时间点在u之前,返回真;否则返回假。

3.7.5 After

func (t Time) After(u Time) bool

如果t代表的时间点在u之后,返回真;否则返回假。

3.8 定时器

使用time.Tick(时间间隔)来设置定时器,定时器的本质上是一个通道(channel)

func tickDemo() {ticker := time.Tick(time.Second) //定义一个1秒间隔的定时器for i := range ticker {fmt.Println(i)//每秒都会执行的任务}
}
time.AfterFunc(time.Second*10, func() {fmt.Println("10秒后执行")
})
func main() {var wg sync.WaitGroupwg.Add(2)//NewTimer 创建一个 Timer,它会在最少过去时间段 d 后到期,向其自身的 C 字段发送当时的时间//2秒后触发timer1 := time.NewTimer(2 * time.Second)//NewTicker 返回一个新的 Ticker,该 Ticker 包含一个通道字段,并会每隔时间段 d 就向该通道发送当时的时间。它会调//整时间间隔或者丢弃 tick 信息以适应反应慢的接收者。如果d <= 0会触发panic。关闭该 Ticker 可//以释放相关资源。//每隔2秒触发一次ticker1 := time.NewTicker(2 * time.Second)go func(t *time.Ticker) {defer wg.Done()for {<-t.Cfmt.Println("get ticker1", time.Now().Format("2006-01-02 15:04:05"))}}(ticker1)go func(t *time.Timer) {defer wg.Done()for {<-t.Cfmt.Println("get timer", time.Now().Format("2006-01-02 15:04:05"))//Reset 使 t 重新开始计时,(本方法返回后再)等待时间段 d 过去后到期。如果调用时t//还在等待中会返回真;如果 t已经到期或者被停止了会返回假。//重置定时器,相当于使其变成周期性定时器t.Reset(2 * time.Second)}}(timer1)wg.Wait()
}

sync.WaitGroup

  • sync.WaitGroup 用来等待一组 goroutine 完成。wg.Add(2) 表示等待 2 个 goroutine 完成任务,wg.Done() 用来标记 goroutine 完成,wg.Wait() 用来阻塞当前 goroutine,直到所有 goroutine 完成。

time.Timertime.Ticker

  • time.NewTimer(d):创建一个定时器,等待 d 时间后向其 C 通道发送当前时间(只会触发一次)。
  • time.NewTicker(d):创建一个定时器,每隔 d 时间向其 C 通道发送当前时间。它会持续触发,直到显式停止。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

快速入门Spring Cloud Alibaba,轻松玩转微服务

​ 1 快速入门Spring Cloud Alibaba&#xff0c;轻松玩转微服务 1.1 架构 架构图&#xff1a; 1.2 项目结构 1.2.1 系统框架版本 版本适配查看&#xff1a;https://sca.aliyun.com/docs/2023/overview/version-explain/ Spring Boot Version &#xff1a;3.2.4 Spring Clo…

腾讯云AI代码助手-每日清单助手

作品简介 每日清单助手是一款可以记录生活的小程序&#xff0c;在人们需要记录时使用&#xff0c;所以根据这个需求来创建的这款应用工具&#xff0c;使用的是腾讯云AI代码助手来生成的所有代码&#xff0c;使用方便&#xff0c;快捷&#xff0c;高效。 技术架构 python语言…

Pytorch学习12_最大池化的使用

输入图像 import torch from torch import nninputtorch.tensor([[1,2,0,3,1],[0,1,2,3,1],[1,2,1,0,0],[5,2,3,1,1],[2,1,0,1,1]]) inputtorch.reshape(input,(-1,1,5,5))#二维张量转换为一个四维张量。(batch_size, channels, height, width)print(input.shape)ceil_modeTrue…

009:传统计算机视觉之边缘检测

本文为合集收录&#xff0c;欢迎查看合集/专栏链接进行全部合集的系统学习。 合集完整版请参考这里。 本节来看一个利用传统计算机视觉方法来实现图片边缘检测的方法。 什么是边缘检测&#xff1f; 边缘检测是通过一些算法来识别图像中物体之间或者物体与背景之间的边界&…

HarmonyOS Next系列之华为账号一键登录功能实现(十四)

系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现&#xff08;一&#xff09; HarmonyOS Next 系列之验证码输入组件实现&#xff08;二&#xff09; HarmonyOS Next 系列之底部标签栏TabBar实现&#xff08;三&#xff09; HarmonyOS Next 系列之HTTP请求封装和Token…

大数据架构设计:数据分层治理的全景指南

大数据架构设计&#xff1a;数据分层治理的全景指南 在大数据架构中&#xff0c;数据分层治理是一种被广泛采用的设计模式&#xff0c;其核心目的是为数据赋予结构化管理的能力&#xff0c;降低复杂度&#xff0c;并为数据的多样化使用场景提供保障。在这篇文章中&#xff0c;…

unity学习14:unity里的C#脚本的几个基本生命周期方法, 脚本次序order等

目录 1 初始的C# 脚本 1.1 初始的C# 脚本 1.2 创建时2个默认的方法 2 常用的几个生命周期方法 2.1 脚本的生命周期 2.1.1 其中FixedUpdate 方法 的时间间隔&#xff0c;是在这设置的 2.2 c#的基本语法别搞混 2.2.1 基本的语法 2.2.2 内置的方法名&#xff0c;要求更严…

Ubuntu中使用miniconda安装R和R包devtools

安装devtools环境包 sudo apt-get install gfortran -y sudo apt-get install build-essential -y sudo apt-get install libxt-dev -y sudo apt-get install libcurl4-openssl-dev -y sudo apt-get install libxml2.6-dev -y sudo apt-get install libssl-dev -y sudo apt-g…

如何在 Windows 10/11 上录制带有音频的屏幕 [3 种简单方法]

无论您是在上在线课程还是参加在线会议&#xff0c;您都可能需要在 Windows 10/11 上录制带有音频的屏幕。互联网上提供了多种可选方法。在这里&#xff0c;本博客收集了 3 种最简单的方法来指导您如何在 Windows 10/11 上使用音频进行屏幕录制。请继续阅读以探索&#xff01; …

Python 中几个库的安装与测试

一、jupyter 安装步骤 确保系统已经安装了Python&#xff08;建议 Python 3.6 及以上版本&#xff09;。点击WinR输入cdm进入命令提示符窗口&#xff0c;然后输入pip install jupyter&#xff0c;按下回车键。等待安装过程完成。安装过程中&#xff0c;你会看到命令行输出安装…

【阅读笔记】基于FPGA的红外图像二阶牛顿插值算法的实现

图像缩放技术在图像显示、传输、分析等多个领域中扮演着重要角色。随着数字图像处理技术的发展&#xff0c;对图像缩放质量的要求也越来越高。二阶牛顿插值因其在处理图像时能够较好地保持边缘特征和减少细节模糊&#xff0c;成为了图像缩放中的一个研究热点。 一、 二阶牛顿插…

5.1 数据库:INSERT 插入语句

工作中增删改查这四类sql语句里边用的最多的就是查询语句。因为绝大多数的软件系统都是读多写少的&#xff0c;而且查询的条件也是各种各样。本节课程我们来学习下一个DML语句&#xff0c;那就是向数据表里面写入记录的insert语句。Insert语句是可以向数据表里边写入&#xff0…

【 算法设计与分析-回顾算法知识点】福建师范大学数学与计算机科学学院 2006 — 2007学年第二学期考试 A 卷

一&#xff0e;填空题&#xff08;每空2分&#xff0c;共30分&#xff09; 1&#xff0e;算法的时间复杂性指算法中 元运算 的执行次数。 2&#xff0e;在忽略常数因子的情况下&#xff0c;O、和三个符号中&#xff0c; O 提供了算法运行时间的一个上界。 3&#xff0e;设Dn…

嵌入式技术之Linux(Ubuntu) 一

一、Linux入门 1.硬件和操作系统以及用户的关系 一个传感器&#xff0c;获得数据后&#xff0c;需要向服务器发送数据。传感器传数据给上位机。 上位机需要一个程序来接收数据&#xff0c;那么这个上位机是什么机器&#xff1f; 我们的笔记本电脑就可以当成上位机。 两个手…

Flink系统知识讲解之:如何识别反压的源头

Flink系统知识之&#xff1a;如何识别反压的源头 什么是反压 Ufuk Celebi 在一篇古老但仍然准确的文章中对此做了很好的解释。如果您不熟悉这个概念&#xff0c;强烈推荐您阅读这篇文章。如果想更深入、更低层次地了解该主题以及 Flink 网络协议栈的工作原理&#xff0c;这里有…

浙江安吉成新的分布式光伏发电项目应用

摘 要&#xff1a;分布式光伏发电站是指将光伏发电组件安装在用户的建筑物屋顶、空地或其他适合的场地上&#xff0c;利用太阳能进行发电的一种可再生能源利用方式&#xff0c;与传统的大型集中式光伏电站相比&#xff0c;分布式光伏发电具有更灵活的布局、更低的建设成本和更高…

IDEA 字符串拼接符号“+”位于下一行的前面,而不是当前行的末尾

效果图 IDEA 默认效果是“历史效果”&#xff0c;经过修改后为“预期效果” 设置方式 在设置中找到Editor > Code Style > Java > Wrapping and Braces > Binary expressions > 勾选 Operation sign on next line 即可实现。具体设置如图。

基于phpstudy快速搭建本地php环境(Windows)

好好生活&#xff0c;别睡太晚&#xff0c;别爱太满&#xff0c;别想太多。 声明 仅作为个人学习使用&#xff0c;仅供参考 对于CTF-Web手而言&#xff0c;本地PHP环境必不可少&#xff0c;但对于新手来说从下载PHP安装包到配置PHP环境是个非常繁琐的事情&#xff0c;因此笔者…

后台管理系统引导功能的实现

引导是软件中经常见到的一个功能&#xff0c;无论是在后台项目还是前台或者是移动端项目中。 那么对于引导页而言&#xff0c;它是如何实现的呢&#xff1f;通常情况下引导页是通过 聚焦 的方式&#xff0c;高亮一块视图&#xff0c;然后通过文字解释的形式来告知用户该功能的作…

vscode通过ssh连接服务器实现免密登录

一、通过ssh连接服务器 1、打开vscode&#xff0c;进入拓展&#xff08;CtrlShiftX&#xff09;&#xff0c;下载拓展Remote - SSH。 2、点击远程资源管理器选项卡&#xff0c;选择远程&#xff08;隧道/SSH&#xff09;类别。 3、点击SSH配置。 4、在中间上部分弹出的配置文件…