如何快速入门一门语言

8196049-6f97aa4b02cd163c.jpg
必应--精美壁纸

最近在看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壁纸的文件夹即可。


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

猜你喜欢

转载自blog.csdn.net/weixin_33869377/article/details/87428951