Golang GoStdLib  
		2021-03-01
		
- archive: 打包 (tar, zip)
 参考:《Golangarchive包》
- compress: 压缩 (bzip2, flate, gzip, lzw, zlib)
压缩 & 解压缩
import (
    "bytes"
    "compress/gzip"
    "io"
)
func compressData(data string) ([]byte, error) {
    var buf bytes.Buffer
    gz := gzip.NewWriter(&buf)
    _, err := gz.Write([]byte(data))
    if err != nil {
        return nil, err
    }
    if err := gz.Close(); err != nil {
        return nil, err
    }
    return buf.Bytes(), nil
}
func decompressData(compressedData []byte) (string, error) {
    r, err := gzip.NewReader(bytes.NewReader(compressedData))
    if err != nil {
        return "", err
    }
    defer r.Close()
    decompressedData, err := io.ReadAll(r)
    if err != nil {
        return "", err
    }
    return string(decompressedData), nil
}
压缩 & 解压缩 & 列出压缩包中的内容
import (
    "archive/zip"
)
// 压缩文件
func compressFile(zipFilename string, filenames ...string) error {
    zipFile, err := os.Create(zipFilename)
    if err != nil {
        return err
    }
    defer zipFile.Close()
    zipWriter := zip.NewWriter(zipFile)
    defer zipWriter.Close()
    for _, filename := range filenames {
        file, err := os.Open(filename)
        if err != nil {
            return err
        }
        defer file.Close()
        fi, err := file.Stat()
        if err != nil {
            return err
        }
        fileHeader, err := zip.FileInfoHeader(fi)
        if err != nil {
            return err
        }
        // 设置文件名(压缩后的文件名)
        fileHeader.Name = filename
        // 写入文件头部
        writer, err := zipWriter.CreateHeader(fileHeader)
        if err != nil {
            return err
        }
        // 复制文件内容到压缩包中
        _, err = io.Copy(writer, file)
        if err != nil {
            return err
        }
    }
    return nil
}
// 解压缩文件
func decompressFile(zipFilename, targetDir string) error {
    zipReader, err := zip.OpenReader(zipFilename)
    if err != nil {
        return err
    }
    defer zipReader.Close()
    for _, file := range zipReader.File {
        // 打开压缩包中的文件
        fileReader, err := file.Open()
        if err != nil {
            return err
        }
        defer fileReader.Close()
        // 创建目标文件
        extractedFilePath := fmt.Sprintf("%s/%s", targetDir, file.Name)
        extractedFile, err := os.Create(extractedFilePath)
        if err != nil {
            return err
        }
        defer extractedFile.Close()
        // 复制文件内容到目标文件
        _, err = io.Copy(extractedFile, fileReader)
        if err != nil {
            return err
        }
    }
    return nil
}
func listFilesInZip(zipFilename string) ([]string, error) {
    files := []string{}
    zipReader, err := zip.OpenReader(zipFilename)
    if err != nil {
        return files, err
    }
    defer zipReader.Close()
    for _, file := range zipReader.File {
        files = append(files, file.Name)
    }
    return files, nil
}
	
	
	
		
		 Golang GoStdLib  
		2021-03-01
		标准库中的 archive 支持 tar,zip 两种打包格式。
https://en.wikipedia.org/wiki/Tar_(computing)
最常用的 tar 包:
func createTarArchive(sourceDir, targetFile string) error {
    file, err := os.Create(targetFile)
    if err != nil {
        return err
    }
    defer file.Close()
    tarWriter := tar.NewWriter(file)
    defer tarWriter.Close()
    return filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        header, err := tar.FileInfoHeader(info, info.Name())
        if err != nil {
            return err
        }
        if err := tarWriter.WriteHeader(header); err != nil {
            return err
        }
        if !info.IsDir() {
            file, err := os.Open(path)
            if err != nil {
                return err
            }
            defer file.Close()
            _, err = io.Copy(tarWriter, file)
            if err != nil {
                return err
            }
        }
        return nil
    })
}
func extractTarArchive(sourceFile, targetDir string) error {
    file, err := os.Open(sourceFile)
    if err != nil {
        return err
    }
    defer file.Close()
    tarReader := tar.NewReader(file)
    for {
        header, err := tarReader.Next()
        if err == io.EOF {
            break
        }
        if err != nil {
            return err
        }
        targetPath := filepath.Join(targetDir, header.Name)
        if err := os.MkdirAll(filepath.Dir(targetPath), 0755); err != nil {
            return err
        }
        if header.Typeflag == tar.TypeReg {
            file, err := os.Create(targetPath)
            if err != nil {
                return err
            }
            defer file.Close()
            _, err = io.Copy(file, tarReader)
            if err != nil {
                return err
            }
        }
    }
    return nil
}
	
	
	
		
		 Golang  
		2021-02-24
		
数组声明时可以使用 ... 当作长度,表示自动判断。
数组声明时,可以只初始化其中的部分值。
a := [...]int{2: 1, 4: 2} // [5]int{0, 0, 1, 0, 4}
b := [5]int{1, 2, 3} // [5]int{1, 2, 3, 0, 0}
基本操作
a := [...]int{1, 2, 3}
var b []int
// 新增
b = append(b, 1)
// 删除元素
s = append(s[:index], s[index+1:]...)
// 遍历
for i := range a {
    fmt.Println(a[i])
}
for index, value := range a {
    fmt.Printf("%v: %v", index, value)
}
for _, value := range a {
    fmt.Printf("%v", value)
}
for i := 0; i < len(array); i++ {
    fmt.Printf("value: %d\n", array[i])
}
// 判断元素是否存在/获取元素序号
func Index(target int, array []int) int {
    for i, v := range array {
        if target == v {
            return i
        }
    }
    return -1
}
示例
package main
import (
    "fmt"
    "reflect"
)
func main() {
    a := [5]int{1, 3, 5, 7, 9}
    fmt.Printf("%s\t%#v\n", reflect.TypeOf(a), a)
    // [5]int   [5]int{1, 3, 5, 7, 9}
    // array => slice
    b := a[:] // a[0:len(a)]
    fmt.Printf("%s\t%#v\n", reflect.TypeOf(b), b)
    // []int    []int{1, 3, 5, 7, 9}
    // slice => array
    // c := ([5]int)(b) // cannot convert b (type []int) to type [5]int
    c := (*[5]int)(b) // 切片只能转换成数组指针
    fmt.Printf("%s\t%#v\n", reflect.TypeOf(c), c)
    // *[5]int  &[5]int{1, 3, 5, 7, 9}
    // 用类型别名试试:
    type NumArr [5]int
    c2 := (*NumArr)(b)
    fmt.Printf("%s\t%#v\n", reflect.TypeOf(c2), c2)
    // *main.NumArr &main.NumArr{1, 3, 5, 7, 9}
    // 只能遍历赋值
    d := [5]int{}
    for index, v := range b {
        d[index] = v
    }
    fmt.Printf("%s\t%#v\n", reflect.TypeOf(d), d)
    // 通过 copy 的方法实现 slice2array
    e := [5]int{}
    copy(e[:], b) // return length of b
    fmt.Printf("%s\t%#v\n", reflect.TypeOf(e), e)
}
去重
func Unique(arr []int) []int {
    arrLen := len(arr) - 1
    for arrLen > 0 {
        for i := arrLen - 1; i >= 0; i-- {
            if arr[arrLen] == arr[i] {
                arr = append(arr[:i], arr[i+1:]...)
                break
            }
        }
        arrLen--
    }
    return arr
}
func UniqueOptimized(arr []int) []int {
    uniqueArr := make([]int, 0, len(arr))
    uniqueMap := make(map[int]struct{})
    for _, num := range arr {
        if _, ok := uniqueMap[num]; !ok {
            uniqueArr = append(uniqueArr, num)
            uniqueMap[num] = struct{}{}
        }
    }
    return uniqueArr
}
// BenchmarkUniqueOriginal-20           135           8658964 ns/op               0 B/op          0 allocs/op
// BenchmarkUniqueOptimized-20         3501            347027 ns/op          285402 B/op        208 allocs/op
可以看到,一个性能好一些(只用 4% 的时间),资源使用多一些。
使用反射
https://blog.csdn.net/youngwhz1/article/details/83026263
func SliceRemoveDuplicate(a interface{}) (ret []interface{}) {
    if reflect.TypeOf(a).Kind() != reflect.Slice {
        fmt.Printf("<SliceRemoveDuplicate> <a> is not slice but %T\n", a)
        return ret
    }
    va := reflect.ValueOf(a)
    for i := 0; i < va.Len(); i++ {
        if i > 0 && reflect.DeepEqual(va.Index(i-1).Interface(), va.Index(i).Interface()) {
            continue
        }
        ret = append(ret, va.Index(i).Interface())
    }
    return ret
}
func SliceInsert(s []interface{}, index int, value interface{}) []interface{} {
    rear := append([]interface{}{}, s[index:]...)
    return append(append(s[:index], value), rear...)
}
func SliceInsert2(s *[]interface{}, index int, value interface{}) {
    rear := append([]interface{}{}, (*s)[index:]...)
    *s = append(append((*s)[:index], value), rear...)
}
func SliceInsert3(s interface{}, index int, value interface{}) bool {
    if ps, ok := s.(*[]string); ok {
        if val, ok := value.(string); ok {
            rear := append([]string{}, (*ps)[index:]...)
            *ps = append(append((*ps)[:index], val), rear...)
            return true
        }
    } else if ps, ok := s.(*[]int); ok {
        if val, ok := value.(int); ok {
            rear := append([]int{}, (*ps)[index:]...)
            *ps = append(append((*ps)[:index], val), rear...)
        }
    } else if ps, ok := s.(*[]float64); ok {
        if val, ok := value.(float64); ok {
            rear := append([]float64{}, (*ps)[index:]...)
            *ps = append(append((*ps)[:index], val), rear...)
        }
    } else {
        fmt.Printf("<SliceInsert3> Unsupported type: %T\n", s)
    }
    return false
}
func SliceRemove(s []interface{}, index int) []interface{} {
    return append(s[:index], s[index+1:]...)
}
func SliceRemove2(s *[]interface{}, index int) {
    *s = append((*s)[:index], (*s)[index+1:]...)
}
func SliceRemove3(s interface{}, index int) bool {
    if ps, ok := s.(*[]string); ok {
        *ps = append((*ps)[:index], (*ps)[index+1:]...)
    } else if ps, ok := s.(*[]int); ok {
        *ps = append((*ps)[:index], (*ps)[index+1:]...)
    } else if ps, ok := s.(*[]float64); ok {
        *ps = append((*ps)[:index], (*ps)[index+1:]...)
    } else {
        fmt.Printf("<SliceRemove3> Unsupported type: %T\n", s)
        return false
    }
    return true
}
func SliceClear(s *[]interface{}) {
    *s = append([]interface{}{})
}
func SliceClear2(s *[]interface{}) {
    *s = (*s)[0:0]
}
func SliceClear3(s interface{}) bool {
    if ps, ok := s.(*[]string); ok {
        *ps = (*ps)[0:0]
        //*ps = append([]string{})
    } else if ps, ok := s.(*[]int); ok {
        *ps = (*ps)[0:0]
        //*ps = append([]int{})
    } else if ps, ok := s.(*[]float64); ok {
        *ps = (*ps)[0:0]
        //*ps = append([]float64{})
    } else {
        fmt.Printf("<SliceClear3> Unsupported type: %T\n", s)
        return false
    }
    return true
}
泛型实现
func Insert[S ~[]E, E any](s S, i int, v ...E) S {
    tot := len(s) + len(v)
    if tot <= cap(s) {
        s2 := s[:tot]
        copy(s2[i+len(v):], s[i:])
        copy(s2[i:], v)
        return s2
    }
    s2 := make(S, tot)
    copy(s2, s[:i])
    copy(s2[i:], v)
    copy(s2[i+len(v):], s[i:])
    return s2
}
内置方法 make
make(Type, Len, Cap) 可以用来为 slice, map, channel 三种类型初始化(类似:C 语言 (int *)malloc(5))。
这里就看 Slice 的情况。
s1 := make([]int, 5)
s2 := make([]int, 5, 10)
// s2[8] = 1 // panic: runtime error: index out of range [8] with length 5
s2 = append(s2, 1)
如果有预留空间,append 的时候可以不用重新分配内存并遍历赋值。
如果切片有扩容的需要,就最好采用 make 来初始化。
如果不指定容量,则切片的容量和长度将相等。
	
	
	
		
		 Golang  
		2021-02-22
		
- 创建临时文件
- 使用编辑器编辑
- 获取内容
- 删除临时文件
package main
import (
    "bufio"
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "os/exec"
)
func main() {
    // create a tmp file
    // ioutil.TempFile creates a temp file and opens the file for reading and writing
    // and returns the resulting *os.File (file descriptor).
    tmpFile, err := ioutil.TempFile(os.TempDir(), "todo-tmp-")
    if err != nil {
        log.Fatal("Cannot create temporary file", err)
    }
    // defer os.Remove(tmpFile.Name())
    defer tmpFile.Close()
    fmt.Println("Created File: " + tmpFile.Name())
    // choose editor by env var
    editor := os.Getenv("EDITOR")
    args := []string{}
    if editor == "" {
        editor = "vim"
        args = append(args, "--clean")
        fmt.Println("No EDITOR enviroment variable set, use " + editor)
    } else {
        fmt.Println("Using EDITOR enviroment variable: " + editor)
    }
    args = append(args, tmpFile.Name())
    fmt.Println("Opening file with " + editor + " with args: " + fmt.Sprint(args))
    // check the editor command is available
    // _, err = exec.LookPath(editor)
    // if err != nil {
    //  log.Fatal("Cannot find editor: " + editor)
    // }
    // call the editor
    cmd := exec.Command(editor, args...)
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    err = cmd.Run()
    if err != nil {
        log.Fatal("Cannot run editor: " + editor)
    }
    // read the file
    // data, err := ioutil.ReadFile(tmpFile.Name())
    // if err != nil {
    //  log.Fatal("Cannot read file: " + tmpFile.Name())
    // }
    tmpFile.Seek(0, 0)
    s := bufio.NewScanner(tmpFile)
    for s.Scan() {
        fmt.Println("Content:\n\n" + s.Text())
    }
    if err = s.Err(); err != nil {
        log.Fatal("error reading temp file", err)
    }
}
	
	
	
		
		 Golang GoStdLib  
		2021-02-21
		func Clone(s string) string                 //
func Compare(a, b string) int               // 比较
func Contains(s, substr string) bool        // 包含子字符串
func ContainsAny(s, chars string) bool      // 包含任意Char
func ContainsRune(s string, r rune) bool    // 包含Rune
func Count(s, substr string) int            // 计数
func Cut(s, sep string) (before, after string, found bool)
func EqualFold(s, t string) bool                    //
func Fields(s string) []string                      // 切割
func FieldsFunc(s string, f func(rune) bool) []string
func HasPrefix(s, prefix string) bool               // 前缀判断 startswith
func HasSuffix(s, suffix string) bool               // 后缀判断 endswith
func Index(s, substr string) int                    // 查找
func IndexAny(s, chars string) int                  // 查找Any
func IndexByte(s string, c byte) int                // 查找Byte
func IndexFunc(s string, f func(rune) bool) int     // 查找Func
func IndexRune(s string, r rune) int                // 查找Rune
func Join(elems []string, sep string) string        // 连接
func LastIndex(s, substr string) int                // 右查找
func LastIndexAny(s, chars string) int              // 右查找Any
func LastIndexByte(s string, c byte) int            // 右查找Byte
func LastIndexFunc(s string, f func(rune) bool) int // 右查找Func
func Map(mapping func(rune) rune, s string) string  //
func Repeat(s string, count int) string             // 重复
func Replace(s, old, new string, n int) string      // 替换
func ReplaceAll(s, old, new string) string          // 替换 = Replace -1
func Split(s, sep string) []string                  // 切割
func SplitAfter(s, sep string) []string             //
func SplitAfterN(s, sep string, n int) []string     //
func SplitN(s, sep string, n int) []string          //
func Title(s string) string                         //
func ToLower(s string) string                       // 转小写
func ToLowerSpecial(c unicode.SpecialCase, s string) string
func ToTitle(s string) string                       // Title
func ToTitleSpecial(c unicode.SpecialCase, s string) string
func ToUpper(s string) string
func ToUpperSpecial(c unicode.SpecialCase, s string) string
func ToValidUTF8(s, replacement string) string
func Trim(s, cutset string) string
func TrimFunc(s string, f func(rune) bool) string
func TrimLeft(s, cutset string) string
func TrimLeftFunc(s string, f func(rune) bool) string
func TrimPrefix(s, prefix string) string
func TrimRight(s, cutset string) string
func TrimRightFunc(s string, f func(rune) bool) string
func TrimSpace(s string) string
func TrimSuffix(s, suffix string) string
type Builder
    func (b *Builder) Cap() int
    func (b *Builder) Grow(n int)
    func (b *Builder) Len() int
    func (b *Builder) Reset()
    func (b *Builder) String() string
    func (b *Builder) Write(p []byte) (int, error)
    func (b *Builder) WriteByte(c byte) error
    func (b *Builder) WriteRune(r rune) (int, error)
    func (b *Builder) WriteString(s string) (int, error)
type Reader
    func NewReader(s string) *Reader
    func (r *Reader) Len() int
    func (r *Reader) Read(b []byte) (n int, err error)
    func (r *Reader) ReadAt(b []byte, off int64) (n int, err error)
    func (r *Reader) ReadByte() (byte, error)
    func (r *Reader) ReadRune() (ch rune, size int, err error)
    func (r *Reader) Reset(s string)
    func (r *Reader) Seek(offset int64, whence int) (int64, error)
    func (r *Reader) Size() int64
    func (r *Reader) UnreadByte() error
    func (r *Reader) UnreadRune() error
    func (r *Reader) WriteTo(w io.Writer) (n int64, err error)
type Replacer
    func NewReplacer(oldnew ...string) *Replacer
    func (r *Replacer) Replace(s string) string
    func (r *Replacer) WriteString(w io.Writer, s string) (n int, err error)
Builder
Reader
Replacer
参考资料与拓展阅读
	
	
	
		
		 Python  
		2021-02-20
		
垃圾回收
Garbage Collector, 简写: GC
Python 垃圾回收是简单基于引用计数
弱引用
在计算机程序设计中,弱引用与强引用相对,是指不能确保其引用的对象不会被垃圾回收器回收的引用。一个对象若只被弱引用所引用,则被认为是不可访问(或弱可访问)的,并因此可能在任何时刻被回收。一些配有垃圾回收机制的语言,如Java、C#、Python、Perl、Lisp等都在不同程度上支持弱引用。
一句话:弱引用不增加计数,对引用计数型 GC 友好一些
垃圾回收与循环引用的问题
import gc
IDS = {}
class A:
    def __del__(self):
        _id = id(self)
        print('A.__del__ %s: 0x%x' % (IDS[_id], _id))
OBJS = {i: A() for i in range(3)}
for i, obj in OBJS.items():
    _id = id(obj)
    IDS[_id] = f'OBJS[{i}]'
    print('%s: 0x%x' % (IDS[_id], _id))
OBJS[1].attr = OBJS[1]
print('1' * 50)
print('====> del OBJS[0]')
del OBJS[0]
print('2' * 50)
print('====> del OBJS[1]')
del OBJS[1]
print('3' * 50)
print('====> del OBJS[2]')
del OBJS[2]
print('4' * 50)
gc.collect()
import weakref
print()
print('=' * 50)
class B:
    def __init__(self, obj):
        self.attrs = [obj]
    def __del__(self):
        _id = id(self)
        print('B.__del__ %s: 0x%x' % (IDS[_id], _id))
a = A()
b = B(a)
a.xyz = b
IDS[id(a)] = 'a'
IDS[id(b)] = 'b'
del a, b  # do nothing
print('=' * 40)
gc.collect()  # will del a and b
print()
print('=' * 50)
class C:
    def __init__(self, obj):
        self.attrs = [weakref.ref(obj)]
    def __del__(self):
        _id = id(self)
        print('C.__del__ %s: 0x%x' % (IDS[_id], _id))
a = A()
c = C(a)
a.xyz = c
IDS[id(a)] = 'a'
IDS[id(c)] = 'c'
del a, c
print('=' * 40)
gc.collect()
标准库:weakref
- class weakref.ref(object[, callback])回调
- weakref.proxy(object[, callback])
- weakref.getweakrefcount(object)
- weakref.getweakrefs(object)
- class weakref.WeakKeyDictionary([dict])
- .keyrefs()
- class weakref.WeakValueDictionary([dict])
- .valuerefs()
- class weakref.WeakSet([elements])- 
- Set class that keeps weak references to its elements. An element will be discarded when no strong reference to it exists any more. 
 
- class weakref.WeakMethod(method)
- class weakref.finalize(obj, func, /, *args, **kwargs)
- weakref.ReferenceType
- weakref.ProxyType
- weakref.CallableProxyType
- weakref.ProxyTypes
import weakref
class Klass:
    pass
obj = Klass()
ref = weakref.ref(obj)
print(ref())
del obj
print(ref())  # None
obj = Klass()
p = weakref.proxy(obj)
print(p)
del obj
print(p)  # ReferenceError: weakly-referenced object no longer exists
参考资料与拓展阅读
	
	
	
		
		 个人 育儿 政策  
		2021-02-17
		参考《国家学生体质健康标准(2014年修订)》,主要看看 90 分的要求。
	
	
	
		
		 Golang GoStdLib GoReflect  
		2021-02-17
		
func Copy(dst, src Value) int
func DeepEqual(x, y any) bool
func Swapper(slice any) func(i, j int)
type ChanDir
    func (d ChanDir) String() string
type Kind
    func (k Kind) String() string
type MapIter
    func (iter *MapIter) Key() Value
    func (iter *MapIter) Next() bool
    func (iter *MapIter) Reset(v Value)
    func (iter *MapIter) Value() Value
type Method
    func (m Method) IsExported() bool
type SelectCase
type SelectDir
type SliceHeader
type StringHeader
type StructField
    func VisibleFields(t Type) []StructField
    func (f StructField) IsExported() bool
type StructTag
    func (tag StructTag) Get(key string) string
    func (tag StructTag) Lookup(key string) (value string, ok bool)
Type
- func ArrayOf(length int, elem Type) Type
- func ChanOf(dir ChanDir, t Type) Type
- func FuncOf(in, out []Type, variadic bool) Type
- func MapOf(key, elem Type) Type
- func PointerTo(t Type) Type
- func PtrTo(t Type) Type
- func SliceOf(t Type) Type
- func StructOf(fields []StructField) Type
- func TypeOf(i any) Type
Value
- func Append(s Value, x ...Value) Value
- func AppendSlice(s, t Value) Value
- func Indirect(v Value) Value
- func MakeChan(typ Type, buffer int) Value
- func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value
- func MakeMap(typ Type) Value
- func MakeMapWithSize(typ Type, n int) Value
- func MakeSlice(typ Type, len, cap int) Value
- func New(typ Type) Value
- func NewAt(typ Type, p unsafe.Pointer) Value
- func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool)
- func ValueOf(i any) Value
- func Zero(typ Type) Value
- func (v Value) Addr() Value
- func (v Value) Bool() bool
- func (v Value) Bytes() []byte
- func (v Value) Call(in []Value) []Value
- func (v Value) CallSlice(in []Value) []Value
- func (v Value) CanAddr() bool
- func (v Value) CanComplex() bool
- func (v Value) CanConvert(t Type) bool
- func (v Value) CanFloat() bool
- func (v Value) CanInt() bool
- func (v Value) CanInterface() bool
- func (v Value) CanSet() bool
- func (v Value) CanUint() bool
- func (v Value) Cap() int
- func (v Value) Close()
- func (v Value) Comparable() bool
- func (v Value) Complex() complex128
- func (v Value) Convert(t Type) Value
- func (v Value) Elem() Value
- func (v Value) Equal(u Value) bool
- func (v Value) Field(i int) Value
- func (v Value) FieldByIndex(index []int) Value
- func (v Value) FieldByIndexErr(index []int) (Value, error)
- func (v Value) FieldByName(name string) Value
- func (v Value) FieldByNameFunc(match func(string) bool) Value
- func (v Value) Float() float64
- func (v Value) Grow(n int)
- func (v Value) Index(i int) Value
- func (v Value) Int() int64
- func (v Value) Interface() (i any)
- func (v Value) InterfaceData() [2]uintptrDEPRECATED
- func (v Value) IsNil() bool
- func (v Value) IsValid() bool
- func (v Value) IsZero() bool
- func (v Value) Kind() Kind
- func (v Value) Len() int
- func (v Value) MapIndex(key Value) Value
- func (v Value) MapKeys() []Value
- func (v Value) MapRange() *MapIter
- func (v Value) Method(i int) Value
- func (v Value) MethodByName(name string) Value
- func (v Value) NumField() int
- func (v Value) NumMethod() int
- func (v Value) OverflowComplex(x complex128) bool
- func (v Value) OverflowFloat(x float64) bool
- func (v Value) OverflowInt(x int64) bool
- func (v Value) OverflowUint(x uint64) bool
- func (v Value) Pointer() uintptr
- func (v Value) Recv() (x Value, ok bool)
- func (v Value) Send(x Value)
- func (v Value) Set(x Value)
- func (v Value) SetBool(x bool)
- func (v Value) SetBytes(x []byte)
- func (v Value) SetCap(n int)
- func (v Value) SetComplex(x complex128)
- func (v Value) SetFloat(x float64)
- func (v Value) SetInt(x int64)
- func (v Value) SetIterKey(iter *MapIter)
- func (v Value) SetIterValue(iter *MapIter)
- func (v Value) SetLen(n int)
- func (v Value) SetMapIndex(key, elem Value)
- func (v Value) SetPointer(x unsafe.Pointer)
- func (v Value) SetString(x string)
- func (v Value) SetUint(x uint64)
- func (v Value) SetZero()
- func (v Value) Slice(i, j int) Value
- func (v Value) Slice3(i, j, k int) Value
- func (v Value) String() string
- func (v Value) TryRecv() (x Value, ok bool)
- func (v Value) TrySend(x Value) bool
- func (v Value) Type() Type
- func (v Value) Uint() uint64
- func (v Value) UnsafeAddr() uintptr
- func (v Value) UnsafePointer() unsafe.Pointer
Golang  
		2021-02-16Golang os 包 中有很多文件系统相关的操作。
创建文件
// *os.File
file, err = os.Create("abc.txt")
if err != nil {
    log.Fatal(err)
}
defer file.Close()
删除文件
os.Remove()
读写文件
// ioutil
func ReadFile(filename string) ([]byte, error)
func WriteFile(filename string, data []byte, perm os.FileMode) error
// os
func Open(name string) (*File, error)
func OpenFile(name string, flag int, perm FileMode) (*File, error)
func ReadFileToString(filename string) ([]string, error) {
    file, err := os.Open(filename)
    if err != nil {
        return nil, err
    }
    defer file.Close()
    scanner := bufio.NewScanner(file)
    var data []string
    for scanner.Scan() {
        line := scanner.Text()
        data = append(data, line)
    }
    if err = scanner.Err(); err != nil {
        return nil, err
    }
    return data, nil
}
// 写
// 如果文件大于指定大小,则截断到指定大小
// 如果文件小于指定大小,则填充到指定大小
file, err := os.Truncate("abc.txt", 1024)
if err != nil {
    log.Fatal(err)
}
裁剪文件(Truncate)
file, err := os.OpenFile("abc.txt", os.O_RDWR, 0644)
if err != nil {
    log.Fatal(err)
}
defer file.Close()
err := file.Truncate(1024)
if err != nil {
    log.Fatal(err)
}
// os.Truncate(path string, size int64) error
err := os.Truncate("abc.txt", 1024)
if err != nil {
    fmt.Println("截断文件失败:", err)
}
创建目录(mkdir)
err := os.Mkdir(dirName, 0755) // 不能创建已经存在的目录
// err := os.MkdirAll(dirPath, 0755) // mkdir -p
if err != nil {
    fmt.Println("创建目录失败:", err)
    return
}
删除目录(rm)
err := os.Remove(dirName) // 不能删除非空目录
// err := os.RemoveAll(dirName) // rm -rf
if err != nil {
    fmt.Println("删除目录失败:", err)
    return
}
查看目录(List/Walk)
dirEntries, err := os.ReadDir(dirPath)
if err != nil {
    return err
}
for _, entry := range dirEntries {
    entryPath := filepath.Join(dirPath, entry.Name())
    if entry.IsDir() {
        fmt.Println("目录:", entryPath)
    } else {
        fmt.Println("文件:", entryPath)
    }
}
package main
import (
    "fmt"
    "os"
    "path/filepath"
)
func visit(path string, info os.FileInfo, err error) error {
    if err != nil {
        fmt.Println("访问目录失败:", err)
        return nil
    }
    if info.IsDir() {
        fmt.Println("目录:", path)
    } else {
        fmt.Println("文件:", path)
    }
    return nil
}
func main() {
    dirPath := "/path/to/directory"
    err := filepath.Walk(dirPath, visit)
    if err != nil {
        fmt.Println("遍历目录失败:", err)
        return
    }
}
查看文件信息(Stat)
fp.Stat()  // 句柄上执行 Stat 方法
fi, err = os.Stat(filepath)
// type FileInfo interface {
//  Name() string       // base name of the file
//  Size() int64        // length in bytes for regular files; system-dependent for others
//  Mode() FileMode     // file mode bits
//  ModTime() time.Time // modification time
//  IsDir() bool        // abbreviation for Mode().IsDir()
//  Sys() any           // underlying data source (can return nil)
// }
// FileMode -> fs.FileMode -> type FileMode uint32
// func (m FileMode) IsDir() bool
// func (m FileMode) IsRegular() bool
// func (m FileMode) Perm() FileMode
// func (m FileMode) String() string
// func (m FileMode) Type() FileMode
// const (
//  // The single letters are the abbreviations
//  // used by the String method's formatting.
//  ModeDir        FileMode = 1 << (32 - 1 - iota) // d: is a directory
//  ModeAppend                                     // a: append-only
//  ModeExclusive                                  // l: exclusive use
//  ModeTemporary                                  // T: temporary file; Plan 9 only
//  ModeSymlink                                    // L: symbolic link
//  ModeDevice                                     // D: device file
//  ModeNamedPipe                                  // p: named pipe (FIFO)
//  ModeSocket                                     // S: Unix domain socket
//  ModeSetuid                                     // u: setuid
//  ModeSetgid                                     // g: setgid
//  ModeCharDevice                                 // c: Unix character device, when ModeDevice is set
//  ModeSticky                                     // t: sticky
//  ModeIrregular                                  // ?: non-regular file; nothing else is known about this file
//  // Mask for the type bits. For regular files, none will be set.
//  ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice | ModeCharDevice | ModeIrregular
//  ModePerm FileMode = 0777 // Unix permission bits
// )
// is exists
func IsNotExist(err error) bool
// 注意:这个方法只有在出现异常,并且异常是路径已存在导致的,才会返回 True
func IsExist(err error) bool
// is dir
if fi.IsDir() {
    ...
}
// is file
if fi.Mode().IsRegular() {
    ...
}
// readable
// writable
// executable
移动文件
os.Rename(src, dst)
复制文件
sourceFile, err := os.Open(sourceFilePath)
if err != nil {
    return err
}
defer sourceFile.Close()
destinationFile, err := os.Create(destinationFilePath)
if err != nil {
    return err
}
defer destinationFile.Close()
_, err = io.Copy(destinationFile, sourceFile)
创建链接
os.Link()
os.Symlink()
临时目录和临时文件
tempFile, err := os.CreateTemp("", "tmp*.txt")  // *os.File
tempFilePath := tempFile.Name()
tempDir, err := os.MkdirTemp("", "tmp") // string
权限
fp.Chmod()
fp.Chown()  // os.Getuid(), os.Getgid()
	
	
	
		
		 开发工具 Windows  
		2021-02-14
		Windows CMD 太挫,中文字体选择少,XP, Win7 下只有点阵字体 (fixedsys) 和新宋体,Win10 字体又多了几个,但效果页不太好。
不过 Win10 的话,可能是半年前吧,微软新出来了一个 Windows Terminal 的虚拟终端,就现代化多了。现在我在 Windows 下(偶尔)一般都是用的新版 Terminal + PowerShell,听方便。
但如果由于 OS 版本等问题,离不开 cmd 的话,有两个方法,一个是使用第三方终端模拟器,比如 cmder;再一个就是想办法定制一下 cmd 的字体。
我在这里记录一下之前使用的一个方案失效地址(确认有效,不过好久都没有用了)。