This is an explanation of the video content.
 用技术延续对ACG的热爱
45

 |   | 

Go实现静态文件服务器

自己写个静态文件服务器,用手机浏览器下载文件

1.简单演示

用 golang 写这种东西太简单了

func main() {
        http.Handle("/", http.FileServer(http.Dir("./")))
        e := http.ListenAndServe(":8080", nil)
        if e != nil {
             fmt.Println(e.Error())
        }
}

关键代码就 2 行

2.自定义目录

用了几次后觉得不爽,要分享哪个目录就得把程序移到该目录下再执行;而且端口是写死的。于是:

func main() {
        dir := "./"
        if len(os.Args) > 1 {
                dir = os.Args[1]
        }
        fmt.Println("[Static file server] start, port:8080")
        http.Handle("/", http.FileServer(http.Dir(dir)))
        e := http.ListenAndServe(":8080", nil)
        if e != nil {
                fmt.Println(e.Error())
        }
}

这样的话,只需要把编译好的程序放到 $PATH 任意目录,用的时候:

file-server path/to/share 0x0002 似乎好多了,不过还有一个尴尬的问题。IP ! 把本机 IP 打印出来岂不更好 最终版本:


//usr/bin/env go run "$0" "$@"; exit "$?"
package main

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

func main() {
        dir := "./"
        if len(os.Args) > 1 {
                dir = os.Args[1]
        }
        ips, _ := localIPs()
        fmt.Println("Local IP addresses:")
        for _, v := range ips {
                fmt.Printf("\t%s\n", v)
        }
        fmt.Println("[Static file server] start, port:8080")
        http.Handle("/", http.FileServer(http.Dir(dir)))
        go func() {
                e := http.ListenAndServe(":8080", nil)
                if e != nil {
                        os.Exit(1)
                }
        }()
        osCh := make(chan os.Signal, 1)
        fmt.Println("Start Signal Hooker!")
        signal.Notify(osCh, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) // , syscall.SIGSTOP) cannot compile on windows
        fmt.Printf("\rGot a signal [%s]\n", <-osCh)

}

// from https://github.com/Akagi201/utilgo/blob/master/ips/ips.go
func localIPs() ([]string, error) {
        var ips []string
        addrs, err := net.InterfaceAddrs()
        if err != nil {
                return ips, err
        }

        for _, a := range addrs {
                if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil {
                        ips = append(ips, ipnet.IP.String())
                }
        }

        return ips, nil
}

基本上大概也许算得上好用了吧,虽然端口还是写死的。

file-server
Local IP addresses:
	192.168.1.67
	172.17.0.1
[Static file server] start, port:8080
Start Signal Hooker!

45 服务端 ↦ Go开发技巧 __ 250 字
 Go开发技巧 #4