欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

从go语言看“如何快速入门一门语言”

程序员文章站 2024-03-19 18:05:16
...

从go语言看“如何快速入门一门语言”

最近在看go语言的语法,使用Python和PHP这种动态语言习惯了之后,再回头使用静态语言,多多少少有点别扭。看了go的语法之后,go给我的最直观的感受就是C+Python,为什么这么说呢?因为从语言的类型角度看,go语言衍生自C语言,很多地方有C语言的身影;但是从易用性和强大的第三方库支持的角度,go语言和Python有异曲同工之妙。

对我来说,学习一门语言,语法可能不是最为重要的,但是这也不是说语法一点都不重要。从陌生到简单的应用大致会有如下阶段:

  • 先大致浏览下这种语言的语法,对变量类型,流程控制,接口实现,然后这个阶段结束后,我们就可以写出简单的脚本了。

  • 再就是对各种库的熟悉,都说站在巨人的肩膀桑,才能看得更远。而go语言有大量的第三方优秀的库,可以大大的简化我们的编码量,并能提高程序的稳定性。

  • 写工具。严格来说,第三个阶段和第二个阶段的界限不是很明显。写自己的一些工具的时候往往会发现更优秀的实现,所以我们拿过来直接用就好,消化吸收到我们自己的代码中。

学习一门语言的目的,实际上就是为了应用。我个人比较推崇的方式就是写工具。漫无目的的去生搬硬套每一个编程范式,意义不是很大。相反,写工具的过程中往往会伴随着各种需求,而这些需求基本上都是我们自己来定义的,所以会有很大的灵活性,对实现每一个小功能,我们都会有比较清晰的认识。这个过程也能不断提升我们应用一门语言的能力。

至于写什么工具,完全有我们自己而定。撇开具体的实现,我们只需要进行大量的头脑风暴即可。天马行空的将我们的设想落地,这就够了。也许你会说,我没有什么特别的需求啊,我要做什么呢?其实,需求是无处不在的,只要去想,总会有的。

另外一个比较好的应用一门语言的例子就是给自己找乐子。当然这个乐子不能保证对每一个人都适用。比如有的人就是喜欢刷题,写算法,现在有很多刷题网站,牛客网,LeetCode等等,都是比较好的去处;但是有的人,比如我对写算法题就不怎么感兴趣,相反,我对写爬虫,做小工具情有独钟,所以我只需要把我的想法用这门语言去实现就好了,这也是一种锻炼,而且从头到尾自身的参与度都很高,对语言的认识也能更透彻一点。当然了,这也只是我自己的看法,其他人也许不这么看。

下面通过一个具体的例子,来“走一遍”应用语言的道路。


需求:给我的Mac弄一些高清壁纸

头脑风暴:

  • 从哪儿能弄到高清壁纸呢?
  • 找到壁纸了怎么能搞到本地呢?
  • 怎么每天自动换壁纸呢?

寻求解决方案:

  • 必应的官网每天都有1920*1080分辨率的高清图片,很精美,就从这搞吧。
  • 刚看了看go语言,就用go语言进行实现吧,这里先不管具体实现,留给后面去思考。
  • Mac有一个功能可以选择一个文件夹,定时切换壁纸。

思考部分:

思考部分是对具体实现的处理,这里就是如何将必应官网的图片下载到本地。这就涉及到网络请求,正则表达式,文件操作。为了更好的使用代码,可以适当的放开一些处理,比如保存位置可以指定,添加额外的参数,这或许就会涉及到命令行参数的使用等等。总之,只要我们具体的去思考实现,就总会有新的需求,伴随而来的就是更多的思考,以及对库和语言的更好的认识,这对于锻炼自己也有一定的帮助。

因此,针对每一个具体的细节,我们就可以将问题细化到每一个小模块。网络请求可以通过http模块解决;正则表达式通过regex处理,字符串拼接、分割等可以使用strings模块,文件操作使用ioutil,os模块处理,命令行参数我们还会使用flag模块来解决等等。

具体实现:
思考完具体的细节,我们就可以着手进行实现了。对于每一个小功能,我们就可以切分到一个个的函数中。下面简单来看下代码:

package main

import (
    "net/http"
    "log"
    "io/ioutil"
        "regexp"
    "strings"
    "os"
    "io"
    "bytes"
    "fmt"
    "flag"
)

// 获取必应首页的背景大图
func DownloadHTML(url string) string {
    resp, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    bytes, error := ioutil.ReadAll(resp.Body)
    if error != nil {
        log.Fatal(error)
    }
    return string(bytes)
}


func GetImageURL(content string) string{
    reg := regexp.MustCompile(`url:(.*?).jpg`)
    ret := reg.FindString(content)
    if len(ret) > 5 {
        // url: "/az/hprichbg/rb/OtterChillin_ZH-CN11488013572_1920x1080.jpg
        ret = "https://cn.bing.com" + strings.Split(ret, "\"")[1]
    }else{
        log.Fatal("解析图片链接出错!")
        ret = ""
    }
    return ret
}

func DownloadImage(url string, folderpath string) int {
    splits := strings.Split(url, "_")
    imagename := splits[len(splits)-2] + ".jpg"

    _, err := os.Stat(folderpath)
    if err != nil {
        log.Fatal("路径:" + folderpath + " 不存在")
    }
    if strings.LastIndex(folderpath, "/") != len(folderpath)-1 {
        folderpath = folderpath + "/"
    }
    imagename = folderpath + imagename

    // 下载图片,保存到本地
    resp, error1 := http.Get(url)
    if error1 != nil {
        log.Fatal(error1)
    }
    defer resp.Body.Close()
    body, _ := ioutil.ReadAll(resp.Body)
    f, error2 := os.Create(imagename)
    if error2 != nil {
        log.Fatal("文件创建失败:", error2)
    }
    io.Copy(f, bytes.NewReader(body))
    // 没有异常,就是正常
    return 0
}

func main() {
    // 图片输出路径
    folder := flag.String("o", "/tmp", "图片输出路径")
    flag.Parse()
    url := "https://cn.bing.com/"
    html := DownloadHTML(url)
    fmt.Println("输出文件路径:", *folder)
    imgurl := GetImageURL(html)
    if ret := DownloadImage(imgurl, *folder); ret==0 {
        fmt.Println("壁纸下载成功啦~")
    }else{
        fmt.Println("对不起,壁纸下载失败!")
    }
}

如此,便可以简单完成我们的预期目标。下面将代码编译出来,通过crontab来每天自动化帮我们抓取图片。

go build daily-bing-wallpaper.go

然后就可以在同级目录下获得daily-bing-wallpaper名称的二进制文件,这样就可以直接执行了。
下面写个crontab,因为我是10点上班,所以安排到10:50去执行就挺合适的。

50 10 * * * cd /abolutepath && ./daily-bing-wallpaper -o /outputpath >> /tmp/get-wallpaper.log 2>&1

最后再设置下Mac壁纸的文件夹即可。


总的来说,找到自己的兴趣点,然后去一点点的实现就好了,过程中对我自己熟悉,应用一门语言也会大有脾益。