V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
bthulu
V2EX  ›  Go 编程语言

golang 咋这么恶心,解压 zip 文件居然要一大串代码,这不应该是语言内置一行搞定的吗?

  •  
  •   bthulu · 2022-12-03 16:43:28 +08:00 · 9236 次点击
    这是一个创建于 502 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这简直不能忍啊

    C#版

    ZipFile.ExtractToDirectory("source", "target");
    

    Golang 版

    func Unzip(src, dest string) error {
        r, err := zip.OpenReader(src)
        if err != nil {
            return err
        }
        defer func() {
            if err := r.Close(); err != nil {
                panic(err)
            }
        }()
    
        os.MkdirAll(dest, 0755)
    
        // Closure to address file descriptors issue with all the deferred .Close() methods
        extractAndWriteFile := func(f *zip.File) error {
            rc, err := f.Open()
            if err != nil {
                return err
            }
            defer func() {
                if err := rc.Close(); err != nil {
                    panic(err)
                }
            }()
    
            path := filepath.Join(dest, f.Name)
    
            // Check for ZipSlip (Directory traversal)
            if !strings.HasPrefix(path, filepath.Clean(dest) + string(os.PathSeparator)) {
                return fmt.Errorf("illegal file path: %s", path)
            }
    
            if f.FileInfo().IsDir() {
                os.MkdirAll(path, f.Mode())
            } else {
                os.MkdirAll(filepath.Dir(path), f.Mode())
                f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
                if err != nil {
                    return err
                }
                defer func() {
                    if err := f.Close(); err != nil {
                        panic(err)
                    }
                }()
    
                _, err = io.Copy(f, rc)
                if err != nil {
                    return err
                }
            }
            return nil
        }
    
        for _, f := range r.File {
            err := extractAndWriteFile(f)
            if err != nil {
                return err
            }
        }
    
        return nil
    }
    
    50 条回复    2022-12-26 15:07:14 +08:00
    XieGP
        1
    XieGP  
       2022-12-03 16:46:48 +08:00   ❤️ 2
    py 写多了吗:)
    loolac
        2
    loolac  
       2022-12-03 16:50:40 +08:00
    当然,还需要一台电脑 ~
    ChrisFreeMan
        3
    ChrisFreeMan  
       2022-12-03 16:51:22 +08:00   ❤️ 3
    真正的逻辑代码也没几行,大部分都是错误处理和 IO 释放
    GeruzoniAnsasu
        4
    GeruzoniAnsasu  
       2022-12-03 17:03:25 +08:00
    C: ……
    yazinnnn
        5
    yazinnnn  
       2022-12-03 17:04:12 +08:00   ❤️ 1
    ?迷惑发言
    wwqgtxx
        6
    wwqgtxx  
       2022-12-03 17:05:55 +08:00   ❤️ 7
    今日迷惑行为大赏
    icepie
        7
    icepie  
       2022-12-03 17:06:53 +08:00   ❤️ 24
    Golang 版
    Unzip("source", "target")
    yazinnnn
        8
    yazinnnn  
       2022-12-03 17:13:17 +08:00   ❤️ 1
    楼主发的这些帖子看上去跟个流量号似的
    ClarkAbe
        9
    ClarkAbe  
       2022-12-03 17:23:52 +08:00 via Android
    zz 发言......自个封装一个就能实现, 你要是懒得封装只能说你不要用这种接近底层的语言了....去 py 吧
    HugoChao
        10
    HugoChao  
       2022-12-03 17:38:46 +08:00
    你代码都有了为什么不封装一下呢
    oldshensheep
        11
    oldshensheep  
       2022-12-03 17:43:30 +08:00   ❤️ 8
    因为
    if err != nil {
    return err
    }
    xavierskip
        12
    xavierskip  
       2022-12-03 17:59:34 +08:00
    你写一个包给大家用不就好了。
    Jooooooooo
        13
    Jooooooooo  
       2022-12-03 18:15:01 +08:00
    golang 的 Unzip 不也是一行?
    heartlose
        14
    heartlose  
       2022-12-03 18:20:13 +08:00
    把这里面封一层再调用不就行了吗
    liuidetmks
        15
    liuidetmks  
       2022-12-03 18:23:03 +08:00 via iPhone
    c 不是更麻烦?
    deorth
        16
    deorth  
       2022-12-03 18:27:51 +08:00 via Android
    要在脑子里打开
    swulling
        17
    swulling  
       2022-12-03 18:30:19 +08:00 via iPhone   ❤️ 1
    https://github.com/artdarek/go-unzip

    随便找个库就行,go 标准库有些比较底层
    shakukansp
        18
    shakukansp  
       2022-12-03 18:36:10 +08:00
    ???
    yanqiyu
        19
    yanqiyu  
       2022-12-03 18:57:09 +08:00   ❤️ 16
    Go 语言并没有将解压 zip 文件作为语言内置的功能,这是因为 Go 的设计理念是尽可能保持简单,而不是提供尽可能多的功能。因此,如果你需要在 Go 中解压 zip 文件,就需要使用第三方库来实现这个功能。这些库通常都提供了一些简单的函数,可以让你在 Go 代码中很容易地解压 zip 文件。比如,你可以使用 Go 语言内置的 "archive/zip" 包来解压 zip 文件,它提供了一个名为" Unzip "的函数,可以让你很容易地解压 zip 文件。

    不是我说的,是 ChatAI 说的🐶
    https://twitter.com/clowwindy/status/1598979812831657984/photo/1
    infinityv
        20
    infinityv  
       2022-12-03 19:08:31 +08:00 via iPhone   ❤️ 3
    @yanqiyu #19 chatgpt 今天给我说 go 是一门动态语言,我说你特么扯淡呢吧,然后他就向我道歉,说我是对的。
    seakingii
        21
    seakingii  
       2022-12-03 19:17:42 +08:00   ❤️ 1
    c#的这个函数方法也是语言内置的,是.NET 类库里的. 语言和库都搞不清楚....
    dw2693734d
        22
    dw2693734d  
       2022-12-03 19:49:49 +08:00
    Golang 确实没有内置的函数来直接解压 zip 文件,但是它提供了一个标准库 "archive/zip",可以用来方便地解压 zip 文件。

    解压 zip 文件的一般步骤如下:

    导入 "archive/zip" 包
    读取 zip 文件内容,比如使用 ioutil.ReadFile()
    创建一个 zip.Reader ,用来处理 zip 文件内容
    遍历 zip.Reader.File ,获取每一个文件,并解压它
    代码示例如下:

    ```
    import (
    "archive/zip"
    "io"
    "io/ioutil"
    "os"
    "path/filepath"
    )

    // 解压 zip 文件
    func unzip(src, dest string) error {
    r, err := zip.OpenReader(src)
    if err != nil {
    return err
    }
    defer r.Close()

    for _, f := range r.File {
    rc, err := f.Open()
    if err != nil {
    return err
    }
    defer rc.Close()

    path := filepath.Join(dest, f.Name)
    if f.FileInfo().IsDir() {
    os.MkdirAll(path, f.Mode())
    } else {
    f, err := os.OpenFile(
    path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
    if err != nil {
    return err
    }
    defer f.Close()

    _, err = io.Copy(f, rc)
    if err != nil {
    return err
    }
    }
    }

    return nil
    }
    ```

    from OpenAI
    MMMMMMMMMMMMMMMM
        23
    MMMMMMMMMMMMMMMM  
       2022-12-03 19:52:11 +08:00   ❤️ 1
    不想造轮子就找 lib 呗,多简单一事

    小编这边推荐你使用易语言哦,不仅也只需要一行,还是中文的哦~
    ghostwind
        24
    ghostwind  
       2022-12-03 19:56:15 +08:00
    go 真正麻烦的解压缩 rar 文件
    LykorisR
        25
    LykorisR  
       2022-12-03 19:58:57 +08:00
    ??
    liaohongxing
        26
    liaohongxing  
       2022-12-03 21:27:20 +08:00
    rar 是专利格式 ,go 官方类库解压 rar 估计不会有 。
    liubaicai
        27
    liubaicai  
       2022-12-03 21:43:03 +08:00
    ZipFile 也不是 c#自带的吧
    leavic
        28
    leavic  
       2022-12-03 21:50:14 +08:00   ❤️ 2
    你们回什么贴啊,block 走人就是了。
    mmdsun
        29
    mmdsun  
       2022-12-03 23:16:09 +08:00   ❤️ 1
    seakingii
        30
    seakingii  
       2022-12-03 23:42:22 +08:00
    @mmdsun 这只是官方实现的库,不是"C#语言自带的功能"...
    微软官方实现的库确实用起来方便,比如 File.WriteAllText , 一次性写入文本到一个文件,也很方便,但和"C#语言自带"这个概念不相符,其实用 VB.NET 一样可以用这些函数,只要.NET 支持的语言都可以.
    seakingii
        31
    seakingii  
       2022-12-03 23:44:45 +08:00
    需求是无穷无尽的,官方也只能挑着实现了,人力毕竟有限
    djoiwhud
        32
    djoiwhud  
       2022-12-04 02:06:12 +08:00 via Android
    go 语言怎么这么恶心。自动把账号功能收到的资金转账到楼主的账号,这么基础的功能都不能自动实现吗?

    本来楼主就要实现万亿资产的目标,都怪 go 太垃圾。
    ewBuyVmLZMZE
        33
    ewBuyVmLZMZE  
       2022-12-04 05:30:34 +08:00
    你贴的代码有一定的安全性问题,可以参考我这个实现。

    https://github.com/bookstairs/bookhunter/blob/master/internal/file/decompress.go
    changyang
        34
    changyang  
       2022-12-04 09:04:38 +08:00
    @yanqiyu 恩必
    LANB0
        35
    LANB0  
       2022-12-04 10:57:11 +08:00
    C:你在说什么? golang 这点代码都还不够我 zip 格式头逐字段解析呢?
    vanton
        36
    vanton  
       2022-12-04 12:29:09 +08:00
    有那么多库可以用,你这样自己找麻烦么
    liubaicai
        37
    liubaicai  
       2022-12-04 12:37:17 +08:00
    @mmdsun “这些示例需要将以下 NuGet 包添加到项目中:” 你仔细看看
    blankmiss
        38
    blankmiss  
       2022-12-04 12:45:55 +08:00
    java 不是一样的 正是因为这样才有很多轮子作者
    JohnBull
        39
    JohnBull  
       2022-12-04 13:20:24 +08:00
    shell 省事,可你嫌不 cool 啊
    oldshensheep
        40
    oldshensheep  
       2022-12-04 13:41:06 +08:00
    @blankmiss Java 可不一样
    https://gist.github.com/oldshensheep/bea5bd4c313f27884bc87dced9917bf6
    带完整的错误处理和流关闭处理,核心函数一共 19 行。
    Fuhuang
        41
    Fuhuang  
       2022-12-04 14:09:16 +08:00
    不,是你原来习惯的.Net 太实用了
    adoyle
        42
    adoyle  
       2022-12-04 14:43:48 +08:00   ❤️ 1
    已 block (善意提醒以后别回我的评论,我看不到的)
    lincanbin
        43
    lincanbin  
       2022-12-04 15:58:22 +08:00
    slice contain 、max 、min 也没有。
    习惯就好。
    bthulu
        44
    bthulu  
    OP
       2022-12-05 08:25:51 +08:00
    @liubaicai 仔细看过了, 并不需要导入任何 nuget 包
    bthulu
        45
    bthulu  
    OP
       2022-12-05 08:29:10 +08:00
    @adoyle block 谁还不会啊, 已 block (善意提醒以后别回我的评论,我也看不到的)
    dragonsunmoon
        46
    dragonsunmoon  
       2022-12-05 16:48:27 +08:00
    只能说明 go 的生态还不行, 自带的标准库比不上 .net 和 java. 开源的工具库项目里, 很少有类似有基金会支持的开源项目, 代码质量和后续维护都令人担忧, 大家都不得不自己造轮子
    dragonsunmoon
        47
    dragonsunmoon  
       2022-12-05 17:33:25 +08:00
    有一说一, go 的标准库是真的简陋, 不好用. 就连个 decimal 标准库里都没有. 感觉设计实现标准库的人, 完全没有做过业务系统, api 的易用性完全是一点都不考虑, 唉...
    blsm
        48
    blsm  
       2022-12-07 14:20:09 +08:00
    go 的生态确实不太行,标准库太简陋了。不内置,官方出个工具包也行
    zhongyitrue
        49
    zhongyitrue  
       2022-12-19 18:17:16 +08:00
    golang 内置不行就是不行,为什么不敢承认呢
    allgy
        50
    allgy  
       2022-12-26 15:07:14 +08:00
    厨子不行怪灶台
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1212 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 23:21 · PVG 07:21 · LAX 16:21 · JFK 19:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.