Skip to main content

· One min read

windows

1, 走http代理

set http_proxy = "http://127.0.0.1:10000"
set https_proxy = "http://127.0.0.1:10000"

2, 走sock5代理

set http_proxy=socks5://127.0.0.1:10000
set https_proxy=socks5://127.0.0.1:10000

示例:可以看到不用任何代理的时候,显示连接超时;使用代理后,立马正常下载

mac

1, 走http代理

#http
export http_proxy = "http://127.0.0.1:1024"
export https_proxy = "http://127.0.0.1:1024"

# for golang
go env -w GOPROXY=https://goproxy.io,direct

2, 走sock5代理

#sockes
export http_proxy = "socks5://127.0.0.1:1024"
export https_proxy = "socks5://127.0.0.1:1024"

· One min read

获取程序的pid很有用

拿到pid之后,你就可以使用操作系统自带的命令来查看更多关于这个pid的信息, eg

ps -p pid -v
package main

import (
"fmt"
"os"
"os/exec"
"strconv"
)

func main() {

pid := os.Getpid()
fmt.Printf("Process PID: %d \n", pid)

prc := exec.Command("ps", "-p", strconv.Itoa(pid), "-v")
out, err := prc.Output()
if err != nil {
panic(err)
}

fmt.Println(string(out))

}

· 2 min read

信号:操作系统和程序之间初级交流方式

它来自古老的c语言,可以通过man signal查看详情

信号列表:

常用的信号有:

  • SIGINTSIGTERM 都是用来终端程序的
  • SIGUP: 程序后台挂起

Golang也可以处理信号, 示例如下:

package main

import (
"fmt"
"os"
"os/signal"
"syscall"
)

func main() {

// Create the channel where the received
// signal would be sent. The Notify
// will not block when the signal
// is sent and the channel is not ready.
// So it is better to
// create buffered channel.
sChan := make(chan os.Signal, 1)

// Notify will catch the
// given signals and send
// the os.Signal value
// through the sChan
signal.Notify(sChan,
syscall.SIGHUP,
syscall.SIGINT,
syscall.SIGTERM,
syscall.SIGQUIT,
syscall.SIGKILL)

// Create channel to wait till the
// signal is handled.
exitChan := make(chan int)
go func() {
signal := <-sChan
switch signal {
case syscall.SIGHUP:
fmt.Println("The calling terminal has been closed")
exitChan <- 0

case syscall.SIGINT:
fmt.Println("The process has been interrupted by CTRL+C")
exitChan <- 1

case syscall.SIGTERM:
fmt.Println("kill SIGTERM was executed for process")
exitChan <- 1

case syscall.SIGKILL:
fmt.Println("SIGKILL handler")
exitChan <- 1

case syscall.SIGQUIT:
fmt.Println("kill SIGQUIT was executed for process")
exitChan <- 1
}
}()

code := <-exitChan //here blocked
os.Exit(code)
}

运行代码,可以看到程序是被block住的:

通过按CTRL + C 发送SIGINT信号给程序, 程序退出

· One min read
# 探测局域网ip
arp -an

# 扫描raspberry ip
arp -na | grep -i "b8:27:eb"
arp -na | grep -i "dc:a6:32"

# 通过terminal 设置 socks5 proxy
networksetup -setsocksfirewallproxy "Wi-Fi" localhost 1086
networksetup -setsocksfirewallproxystate "Wi-Fi" on
networksetup -setsocksfirewallproxystate "Wi-Fi" off

# 查看盘符
diskutil list
# unmount /XX/XXX: 卸载盘符
diskutil unmountdisk /XX/XXX

· One min read
package main

import (
"os"
"os/signal"
"syscall"

"github.com/scott-x/slimx_backup/engine"
)

func main() {
go engine.Run() //MAIN PROCESS
quit := make(chan os.Signal)
signal.Notify(quit, syscall.SIGKILL, syscall.SIGQUIT, syscall.SIGINT, syscall.SIGTERM)
<-quit
}

· 5 min read

对于一门编程语言来说,代码格式化是最容易引起争议的一个问题,不同的开发者可能会有不同的编码风格和习惯,但是如果所有开发者都能使用同一种格式来编写代码,开发者就可以将宝贵的时间专注在语言要解决的问题上。

gofmt介绍 Golang的开发团队制定了统一的官方代码风格,并且推出了gofmt工具(gofmt或go fmt)来帮助开发者格式化他们的代码到统一的风格。gofmt是一个cli程序,会优先读取标准输入,如果传入了文件路径的话,会格式化这个文件,如果传入一个目录,会格式化目录中所有.go文件,如果不传参数,会格式化当前目录下的所有.go文件。

gofmt默认不对代码进行简化,使用-s参数可以开启简化代码功能,具体来说会进行如下的转换:

去除数组、切片、Map初始化时不必要的类型声明:

//如下形式的切片表达式:
[]T{T{}, T{}}
//将被简化为:
[]T{{}, {}}

去除数组切片操作时不必要的索引指定

//如下形式的切片表达式:
s[a:len(s)]
//将被简化为:
s[a:]

去除迭代时非必要的变量赋值

//如下形式的迭代:
for x, _ = range v {...}
//将被简化为:
for x = range v {...}
//如下形式的迭代:
for _ = range v {...}
//将被简化为:
for range v {...}

gofmt命令参数列表如下:

usage: gofmt [flags] [path ...]
-cpuprofile string
write cpu profile to this file
-d display diffs instead of rewriting files
-e report all errors (not just the first 10 on different lines)
-l list files whose formatting differs from gofmt's
-r string
rewrite rule (e.g., 'a[b:len(a)] -> a[b:]')
-s simplify code
-w write result to (source) file instead of stdout

可以看到,gofmt命令还支持自定义的重写规则,使用-r参数,按照pattern -> replacement的格式传入规则。

有如下内容的Golang程序,存储在main.go文件中。

package main

import "fmt"

func main() {
a := 1
b := 2
c := a + b
fmt.Println(c)
}

用以下规则来格式化上面的代码。

gofmt -r "a + b -> b + a"

格式化的结果如下。

package main

import "fmt"

func main() {
a := 1
b := 2
c := b + a
fmt.Println(c)
}

注意:Gofmt使用tab来表示缩进,并且对行宽度无限制,如果手动对代码进行了换行,gofmt也不会强制把代码格式化回一行。

go fmt和gofmt

gofmt是一个独立的cli程序,而go中还有一个go fmt命令,go fmt命令是gofmt的简单封装。

usage: go fmt [-n] [-x] [packages]

Fmt runs the command 'gofmt -l -w' on the packages named
by the import paths. It prints the names of the files that are modified.
For more about gofmt, see 'go doc cmd/gofmt'.
For more about specifying packages, see 'go help packages'.
The -n flag prints commands that would be executed.
The -x flag prints commands as they are executed.
To run gofmt with specific options, run gofmt itself.

See also: go fix, go vet.

go fmt命令本身只有两个可选参数-n和-x,-n仅打印出内部要执行的go fmt的命令,-x命令既打印出go fmt命令又执行它,如果需要更细化的配置,需要直接执行gofmt命令。

go fmt在调用gofmt时添加了-l -w参数,相当于执行了gofmt -l -w

· 2 min read

首先,我们要理解时间戳的概念

然而前端获取的时间戳却是毫秒级的(13位):

不管是s级、ms级、还是us级 时间戳都是int64位的

所以问题转化为如何把 int64转化为 time.Time

time包提供了下面3个api,分别针对不同的时间单位:

  • func Unix(sec int64, nsec int64) Time: s
  • func UnixMilli(msec int64) Time:ms
  • func UnixMicro(usec int64) Time:us

我们要做的就是选择正确的API,那么如何选择呢?

我们可以根据时间戳的位数来判断,假设n为时间戳:

s => 10位 time.Unix(n,0)

ms => 13位 time.UnixMilli(n)

us => 16位 time.UnixMicro(n)

EXAMPLE:

package main

import (
"time"
"fmt"
)

func main() {
var n int64 = 1631504561000;
var t = time.Unix(n,0) //处理秒级的n
fmt.Println(t.Format("2006-01-02 15:04:05")) //53670-04-27 23:23:20 发现结果不对


var t1 = time.UnixMilli(n) //处理ms级的 go version go1.17 才有这个api
fmt.Println(t1.Format("2006-01-02 15:04:05")) //2021-09-13 11:42:41
}

· One min read
  • os.Getwd(): 为动态路径,你终端cd到哪里,它就取当前的dir(等价于./),用于做小工具。
  • os.Getenv(): 路径是写死的,唯一的,用于指定配置文件的位置

· One min read

API

example:

package main

import (
"fmt"
"reflect"
)

type B struct {
}

func main() {
a := "123"
fmt.Println(reflect.TypeOf(a)) //string
var b B
fmt.Println(reflect.TypeOf(b)) //main.B
}

为什么要检测变量类型?

  1. 前端传过来的数据,比如说bool,int你不知道会转化成什么类型
  2. 使用别人的库,你也不知道实例是什么类型

gin拿到的都是string