Golang url 參數編碼與解碼

package main

import (
"fmt"
"net/url"
)

func main() {
urltest := "http://www.baidu.com/s?wd=自由度"
fmt.Println(urltest)
encodeurl:= url.QueryEscape(urltest)
fmt.Println(encodeurl)
decodeurl,err := url.QueryUnescape(encodeurl)
if err != nil {
fmt.Println(err)
}
fmt.Println(decodeurl)
}



輸出結果:
http://www.baidu.com/s?wd=自由度
http%3A%2F%2Fwww.baidu.com%2Fs%3Fwd%3D%E8%87%AA%E7%94%B1%E5%BA%A6
http://www.baidu.com/s?wd=自由度



常在處理網址的人應該會發現某些網址在從瀏覽器複製下來之後,就會變成一些百分比加上十六進位碼的奇怪網址,而貼回去瀏覽器又變正常了,就個就是網址 URL 百分比編碼的問題。

網址 URL 百分比編碼
在 RFC 3986 標準中規範一些 URI 的保留字元(reserved characters),若網址中出現這些保留字元時,就必須把這些保留字元轉為百分比編碼的表示方式,例如:!、#、: 與 & 等。

百分比編碼的規則就是把字元的 ASCII 碼以十六進位表示,前方再加上一個百分比符號,例如井字號 # 的 ASCII 碼是 0x23,所以經過百分比編碼轉換之後,就是 %23。

若是遇到非 ASCII 的字元(例如中文字),則會將資料以 UTF-8 的編碼方式表示成一連串的位元組序列,再將每個位元組以百分比編碼的方式進行編碼。

關於網址的百分比編碼介紹,可以參考維基百科的 Percent-encoding 說明。

平常最常會遇到的網址百分比編碼的地方就是瀏覽器的網址列,當我們在用 Google 搜尋後,若想要把網址複製起來,有時候就會遇到這種編碼問題:


雖然在瀏覽器的網址列中看到的中文字是正常顯示的,但是如果將這串文字複製起來,貼在一般的文字編輯器時,就會出現這樣經過編碼的 URL 網址:

https://www.google.com.tw/search?q=%E4%B8%AD%E6%96%87

原本網址的中文兩個字,在這裡變成了 %E4%B8%AD%E6%96%87,就這是因為瀏覽器在使用者複製網址時,自動把網址經過一道百分比編碼轉換了,事實上這才是標準的網址寫法。

HTML 的 form 表單在用 GET 或 POST 等管道送出資料時(content-type 為 application/x-www-form-urlencoded),其欄位名稱以及資料內容也會經過百分比編碼,不過在編碼規則上有一些小改變(請參考 W3C 網站),最常見的差異就是原本的空白字元會被編碼成 %20,而在這裡就會轉為加號 +。

這個差異在瀏覽器的網址列就可以時常看到,當我們在 Google 搜尋含有空白的關鍵字時,網址會變成這樣:


在 HTTP 的 GET 參數中的空白會被瀏覽器轉換為加號 +,所以 Google 搜尋 ubuntu linux 的網址會變成這樣:

https://www.google.com.tw/search?q=ubuntu+linux
簡單來說,在網址中問號 ? 左邊的空白會轉換成 %20,而右邊的空白則會轉換成 +。

Golang Web 编程的 Get 和 Post 請求發送與解析

通过一个简单的例子介绍Golang的Web编程主要用到的技术。

          文章结构包括:

Client-Get 请求
Client-Post 请求
Server 处理 Get 和 Post 数据
          在数据的封装中,我们部分采用了json,因而本文也涉及到Golang中json的编码和解码。



一、Client-Get

package main

import (
        "fmt"
        "net/url"
        "net/http"
        "io/ioutil"
        "log"
)

func main() {
        u, _ := url.Parse("http://localhost:9001/xiaoyue")
        q := u.Query()
        q.Set("username", "user")
        q.Set("password", "passwd")
        u.RawQuery = q.Encode()
        res, err := http.Get(u.String());
        if err != nil {
              log.Fatal(err) return
        }
        result, err := ioutil.ReadAll(res.Body)
        res.Body.Close()
        if err != nil {
              log.Fatal(err) return
        }
        fmt.Printf("%s", result)
}


二、Client-Post

package main

import (
        "fmt"
        "net/url"
        "net/http"
        "io/ioutil"
        "log"
        "bytes"
        "encoding/json"
)

type Server struct {
        ServerName string
        ServerIP   string
}

type Serverslice struct {
        Servers []Server
        ServersID  string
}


func main() {

        var s Serverslice

        var newServer Server;
        newServer.ServerName = "Guangzhou_VPN";
        newServer.ServerIP = "127.0.0.1"     
        s.Servers = append(s.Servers, newServer)

        s.Servers = append(s.Servers, Server{ServerName: "Shanghai_VPN", ServerIP: "127.0.0.2"})
        s.Servers = append(s.Servers, Server{ServerName: "Beijing_VPN", ServerIP: "127.0.0.3"})
       
        s.ServersID = "team1"

        b, err := json.Marshal(s)
        if err != nil {
                fmt.Println("json err:", err)
        }

        body := bytes.NewBuffer([]byte(b))
        res,err := http.Post("http://localhost:9001/xiaoyue", "application/json;charset=utf-8", body)
        if err != nil {
                log.Fatal(err)
                return
        }
        result, err := ioutil.ReadAll(res.Body)
        res.Body.Close()
        if err != nil {
                log.Fatal(err)
                return
        }
        fmt.Printf("%s", result)
}


三、Server

package main

import (
        "fmt"
        "net/http"
        "strings"
        "html"
        "io/ioutil"
        "encoding/json"
)

type Server struct {
        ServerName string
        ServerIP   string
}

type Serverslice struct {
        Servers []Server
        ServersID  string
}

func main() {
        http.HandleFunc("/", handler)
        http.ListenAndServe(":9001", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
        r.ParseForm() //解析参数,默认是不会解析的
        fmt.Fprintf(w, "Hi, I love you %s", html.EscapeString(r.URL.Path[1:]))
        if r.Method == "GET" {
                fmt.Println("method:", r.Method) //获取请求的方法

                fmt.Println("username", r.Form["username"])
                fmt.Println("password", r.Form["password"])

                for k, v := range r.Form {
                        fmt.Print("key:", k, "; ")
                        fmt.Println("val:", strings.Join(v, ""))
                }
        } else if r.Method == "POST" {
                result, _:= ioutil.ReadAll(r.Body)
                r.Body.Close()
                fmt.Printf("%s\n", result)

                //未知类型的推荐处理方法

                var f interface{}
                json.Unmarshal(result, &f)
                m := f.(map[string]interface{})
                for k, v := range m {
                        switch vv := v.(type) {
                                case string:
                                        fmt.Println(k, "is string", vv)
                                case int:
                                        fmt.Println(k, "is int", vv)
                                case float64:
                                        fmt.Println(k,"is float64",vv)
                                case []interface{}:
                                        fmt.Println(k, "is an array:")
                                        for i, u := range vv {
                                                fmt.Println(i, u)
                                        }
                                default:
                                        fmt.Println(k, "is of a type I don't know how to handle")
                         }
                  }

                 //结构已知,解析到结构体

                 var s Serverslice;
                 json.Unmarshal([]byte(result), &s)

                 fmt.Println(s.ServersID);
 
                 for i:=0; i<len(s.Servers); i++ {
                         fmt.Println(s.Servers[i].ServerName)
                         fmt.Println(s.Servers[i].ServerIP)
                 }
        }
}

電池電量校正

所謂「斷崖式掉電」,另一個說法是「跳電」,
網路上有大量關於手機「斷崖式掉電」的發文,蘋果、小米,各種品牌的都有,
即是手機剩餘電量驟減,如前一秒電量還剩餘50%,後一秒電量就剩下不到20%,又過了幾秒鐘,手機顯示電量不足10%,隨後就自動關機,嘗試開機時顯示低電量無法開機。

那麼,到底是什麼導致了跳電?主要有兩種情況,接觸問題與使用環境溫度過低。

因接觸問題產生跳電,對於拆解過手機或更換過電池的用戶來說,因為這種原因產生的跳電大多伴隨著手機重新啟動。

若是由於使用環境溫度過低導致,當使用環境溫度上升後即可恢復正常使用。

若不是上述兩種情況,則試試看電池電量校正能否修復...


以 iPhone 來說:

1. 想辦法把 iPhone 的電池用盡,用到完全沒電直到 iPhone 自行關機。
2. 等完全沒電之後,接上充電器。
3. 由於之前是用到自行關機,所以電力需要先充到大約2%左右,iPhone 才會顯示畫面,這時候把 iPhone 關機 (長按休眠鍵,一直到出現『滑動來關機』提示出現,然後滑動關機)。
4. 接下來就讓 iPhone 持續充電,充到100% (一般三個多小時可以充飽),充到100%之後,先別拔掉充電線,繼續再多充個一到兩個小時。
5. 接著開機 (還是不要拔掉充電線)。
6. 等iPhone開完機以後,同時按下休眠鍵以及Home鍵,一直按著,直到白底黑蘋果Logo出現為止。
7. OK,電池校正好了。

註:iPhone 處在關機狀態時,一插電就會自動開機,這是一種固定不可改的機制,是用以預防 休眠鍵 故障時,因而導致無法開機的備用手段。

小米做手機、掃地機器人都大賣,攻占不同市場的關鍵是?

「我不需要你用黃金的價格把稻草賣出去,」小米創辦人雷軍說。他在 2010 年創立的這家企業,以「永遠維持 5% 毛利率」「創造高性價比產品」為宗旨,不斷打破各種產業規則,每推出一款商品,就可能造成該商業領域爆炸性的改變,例如當他們所做的行動電源、延長線、小米耳機,都在在改變了該產品領域的定價,以及消費者對於產品質量的要求程度。

從賣手機起家,眾人曾以為「又是一間山寨企業」的小米,在短短 8 年內一路轉型,竄入小家電、生活消費品、電腦與電視產品,在做電腦的同時,也一樣生產掃地機器人、牙刷、延長線。這些分散於不同領域的眾多商品,命運出奇的雷同:在小米生產商品時沒人在意、小米宣告進軍時被眾人訕笑,在小米確定拿下大量市場分額時,又博得眾人的注意和好奇。
小米究竟是怎麼辦到的?雷軍如何能不斷創造大量高性價比的爆品,構成專屬於小米的新商業模式?答案就在 ──「小米生態系」。

「小米生態鏈」是什麼?

時間得回到要 2013 年中,雷軍交辦小米科技聯合創始人暨副總裁劉德,「到市場上去搶一批創業團隊,用小米價值觀孵化一批企業。」

當年選定的第一項產品就是手機周邊商品 ── 行動電源,背後的生產製造公司是「紫米」。再來陸續出現做小米耳機的「萬魔聲學」(1 MORE)、做小米手環等智能可穿戴式裝置的「華米」、做淨水器的「雲米」及平衡車的「納恩博」等等,逐步攻占各個市場領域,形成小米生態圈。

這個生態圈以手機為圓心,向外慢慢發展成三大圈,頭兩層是小米的老本行、雷軍認為還大有可為的手機周邊商品及智慧硬體產品;最外層則是擁有巨大市場的生活耗材類產品。在小米的公開招股書中載明,截至 2018 年 3 月 31 日為止,小米透過投資和管理,建立了由超過 210 家公司組成的生態鏈,其中,有高達 90 多家專注於研發智慧硬體設備與生活消費用品。根據艾瑞諮詢根據 2017 年及 2018 年第一季的統計,行動電源、空氣清淨機與電動滑板車出貨量全球第一的企業,皆隸屬於小米生態鏈。

第一層手機: 智慧型手機
第二層手機周邊: 行動電源(紫米)、耳機(藍米、萬魔聲學)、自拍棒(悅米)
第三層智慧硬體: 空氣清淨機(智米)、智能手環(華米)、電視(峰米)、掃地機器人(石頭科技)、電飯鍋(純米)
第四層生活耗材: 牙刷(貝醫生)、毛巾(最生活)、背包與行李箱(90 分)

對雷軍與小米高層而言,小米生態系的主要定義是「這是一個基於企業生態的智慧硬體設備孵化器」。小米提出三大主張,包括小米只投資、不控股;小米完全輸出產品方法論與價值觀,主導設計、協助研發與尋找供應鏈,並且在自營通路上上架販售;生態鏈企業全數是獨立企業,可獨立研發與銷售自有商品。

也因此,小米與小米生態系旗下眾多企業不是單純的代工關係、也不是單純的投資,更不是母子企業的從屬關係,他們更像是在 IoT 生態下,一群圍繞著「小米精神」、擁有共同思維與企業文化,快速生產、製造與研發各種領域商品的戰略夥伴。

在小米生態系出現之前,這種商業模式前所未見,自然無人可以仿效。雷軍為什麼要這樣做?這對小米的市場地位有什麼樣的幫助?主要來自於他的兩個判斷:

1. 下一個市場在物聯網(IoT)

小米創立時是中國的互聯網元年,當時正巧趕上中國大陸從一般型手機,轉換至智慧型手機的換機潮,也因此才能在 3 年間飛速成長。雷軍認為,物聯網是下一個風口,小米不能錯過。


2. 速度、速度,還是速度

但要趕上這波熱潮,單靠小米之力絕對做不到。雷軍判斷,當年小米有 8000 名員工、其中 2000 名工程師專注於研發手機,卻仍舊趕不上市場速度。單是手機如此,遑論要往外擴展到手機周邊、生活消費硬體設備,人力、專業度、效率與成本,都不能單押在小米一家企業身上。因此,雷軍才有了「去投資一批企業」的想法,意即,

小米要以「投資加孵化」的方式找一堆公司組團打群架,一起布局市場。

雷軍想像,當小米生態鏈有 100 間企業,那就有可能會有 100 個產品進入不同的產業「抱團打拚」,這不只會改善市場,也會改善供應鏈結構,雷軍甚至認為,建構了這個複雜的生態鏈系統,有機會在新零售、AIoT(人工智慧結合物聯網)的環境下,出現一個能超越 BAT(中國三大品牌百度、阿里巴巴、騰訊)三座大山的彎道。

小米 2018 年第 3 季財報,或許證實了雷軍當初的想像。集團季營收將近 508.46 億人民幣,較去年同期增長 49.1%,其中手機商品銷量達 3 億 3300 萬支,約進帳 350 億元人民幣,較去年同期增長 36.1%,但更值得注意的是其 IoT 與生活消費產品營收為 108 億元人民幣,占總營收 21.3%,相較去年成長 89.8%,幅度驚人。

誰才能加入生態鏈,一起打群架?

那誰有資格加入?洪華說,早期小米的投資者都是一群工程師,這群人徹底了解小米的價值觀、對於產品的標準,也對企業極度忠誠,不會因為投資中間所產生的利潤而被誘惑。他們選擇投資標的,只看產品與技術,不看商業計畫與估值,主要原因是「沒必要」,產品太新還沒有市場,而且小米投資的本質是「孵化」,相中有未來發展性的產品更重要。

除了產品之外,他們更在意「被投資人」,雷軍喜歡找熟人,業界說他「衣不如新,人不如故」。智米的蘇峻,是劉德以前在大學教書時的老朋友;小貝醫生的章駿,則是洪華大學時期的學弟。洪華解釋,小米最在意的是被投資者的「價值觀」契合度,包括「不賺快錢」「矢志做最好的產品」「認為互聯網是有未來的」「願意為了改造傳統行業,致力提升效率」等等。

例如純米創辦人楊華,為了做好電子鍋,他們先「蒐集」了全球好用、評價好的產品,全數拿回來研究;再者,他們還到日本向擁有電子鍋多項專利的發明人內藤毅求教;雲米在開發淨水器時,發現市售淨水器都有漏水問題,他們沒打算放過,而是決意升級解決產品的「產業級痛點」,開發商品的過程中產生 400 多項專利、發明專利有 100 個、創新率達 90% 以上,這為淨水器產品立下了相當性的門檻,讓競爭對手難以模仿與超越。

當你加入小米生態鏈之後,小米會提供資源,幫助生態鏈的企業孵化出爆品、成為有能力自主經營的公司。這些資源可分為小米的核心粉絲(人)、小米做爆品的方法和邏輯(貨)、小米的通路和銷售場域(場)三大部分,從新零售的「人、貨、場」三大元素,分析小米商業模式的成功邏輯。


恭喜,貴公司得標了,然後勒?

終於標下大案子!除了慶祝、獎勵員工,還有一件事主管更該做

某公司為了爭取一個大客戶,專門成立了專案組,分工協作,努力半年,經歷各種挫折和辛苦,當然也有各種鼓勵和改進,終於得到了客戶的認可:「恭喜,貴公司得標了。」
這時候公司負責人應該幹什麼?

做兩件事:第一,帶著團隊去狂歡;第二,帶領大家走進會議室,認真地進行一次「復盤」。

哈佛大學的大衛.葛文(David A. Garvin)教授認為:學習型組織的診斷標準之一,就是「不犯曾經犯過的錯誤」。 從即將結束的項目中總結成功經驗,吸取失敗教訓,這就是「復盤」。

聯想公司根據實際經驗,把復盤歸納為 4 個步驟: 回顧目標、評估結果、分析原因和總結規律。

回到最初的案例。按照聯想的復盤流程,可以有如下做法:

一、回顧目標

回顧目標,就是要準確、客觀的回答兩個問題:我們的目標是什麼?我們的里程碑有哪些?

「我們的目標是不顧一切拿下這個項目。」這準確、客觀嗎?這個目標很含糊,什麼叫「不顧一切」?準確、客觀的描述是:「我們要在 10% 毛利率的底線內,拿下這個項目。」

那里程碑呢?「我們的里程碑,是三月底拿下項目,六月份測試上線,九月份收回全款。」

二、評估結果

這一步很關鍵。通過準確、客觀的描述結果,可以找到相對於目標的「好的差異」和「壞的差異」。

比如,結果是:「我們在二月底拿下了項目,但測算的毛利率只有 5%。」因此,好的差異是:我們推動客戶提前做出決定;壞的差異是:毛利率低於預期。

評估結果、描述差異時需要注意,不要忍不住分析原因,甚至提出解決方案,更不要忍不住指責、抱怨和撇清責任。

三、分析原因

評估完結果,就要分析原因:是什麼導致了「好的差異」和「壞的差異」?

大家討論後認為,推動客戶提前做出決定,讓競爭對手措手不及的原因是:

第一次使用了「作戰指揮室」的管理方式,團隊合作的效果和效率都大大提升,使項目方案極具說服力。

銷售嚴格執行「銷售漏斗」流程,發現客戶對上線日期的擔憂,從而說服客戶提前招標。

但是,毛利率為什麼低於預期呢?經過對事不對人的冷靜分析後,大家發現原因是:

項目方案內容變化太快,導致成本估算表更新速度跟不上。

最終一輪談判時,在談判技巧上,表現嚴重不足。

分析原因時要注意:成功主要看「客觀原因」,失敗主要看「主觀原因」。

註:
成功主要看「客觀原因」=>「成功者找方法,失敗者找藉口。」
失敗主要看「主觀原因」=>「做事失敗後,不找客觀原因,找自身原因。」

四、總結規律

公司負責人很高興大家能客觀地面對成敗,獲得的不僅是勝利,更是成長。但是,復盤還沒結束。還有最後一步,也是最重要的一步:總結規律。 這一步,是把「隱性知識顯性化」的關鍵一步。

根據對成敗原因的分析,總結出四條規律:

1. 作戰指揮室,是在重大項目中建立快速反應團隊的好方法。
2. 銷售漏斗培訓,對提高銷售能力值、提高項目成功率很有幫助。
3. 項目方案快速調整時,成本預算表是容易滯後的模塊。
4. 談判能力,在大項目的最後環節,作用明顯。

基於這四點,要開始做什麼、停止做什麼、繼續做什麼呢?

1. 「開始」做兩件事

行政部把一個會議室改成專門的作戰指揮室。

銷售部修改工作手冊,超過三百萬元的項目談判,配備談判專家。

2. 「停止」做一件事

項目內容大量變更時,方案中心不能獨自作戰,要申請財務部專員配合。

3. 「繼續」做一件事

每個新入職的銷售人員,都要參加銷售漏斗培訓。

最後,把復盤總結發給所有人;把總結的規律,寫進工作手冊;把要開始做、停止做的每件事,都啟動單獨的 PDCA 循環。

組織學習大師彼得.聖吉(Peter M. Senge)曾講過:

從本質上看,人類只能通過「試錯法」進行學習。復盤,就是從曾經試過的錯中學習,把經驗和教訓變成組織能力。


2019年1月的全球經濟情勢快照

每當聯準會 (Fed) 主席鮑爾說,他會持續做出過去二年 Fed 所做的事,即緩慢調高聯邦基金利率,並縮減資產負債表,市場投資人便悶悶不樂。

鮑爾的前任 Fed 主席葉倫與伯南克長期維持利率於極低水準,還三度大幅買進債券 (即量化寬鬆),使得股市持續上漲,經濟亦自大衰退中,緩慢復甦,同樣一群投資人却不知心存感激。

現在,他們懇切要求 Fed 別拿走這項利多。

每當鮑爾談話有點鷹派,即他相信經濟仍然強勁,當會繼續升息,股市便告下跌。每當他的措辭有點軟化,股市則又上漲。

目前並沒有證據顯示鮑爾的經濟基本面展望有所改變。他使用與葉倫同樣的措辭 -- 即呼籲緩慢升息,但他的行動較葉倫積極地多。自葉倫於 2015 年 12 月開始升息以來,Fed 已升息九次,却有近半數係發生在鮑爾任內,而到 2 月 5 日,他才上任滿一週年。

當然,對大企業與富人減稅,拉抬了經濟成長。預估 2018 年,美國 GDP 成長將達 3%,創 2015 年以來最高水準。去年就業成長達 260 萬人,高於 2017 年的 220 萬人。

同時,至 6 月,美國經濟復甦將達十年之久,而聯邦基金利率僅 2.25% 至 2.5%。在以往的經濟復甦中,葛林斯班與伯南克僅花了二年半時間,便將利率由 1% 調高到 5.25%。

鮑爾的心態難以捉摸,但他非常了解伯南克調降利率十次,降幅達五個百分點,以對抗金融危機與大衰退。Fed 還注入資產負債表逾 3.5 兆美元資金。除非鮑爾進一步升息,至少達到中性的 3%,否則他將沒有足夠的子彈,對抗下一波經濟衰退。如果不趁著經濟強勁時,縮減資產負債表,可能永遠也無法再做了。

2013 年,鮑爾曾敦促伯南克停止買進債券,展現他的鷹派立場。但現在,他必須保守,避免股市大跌,避免影響經濟。

但如果經濟依舊強勁,市場也穩定,預期他將持續縮減資產負債表,並調高聯邦基金利率,只是速度可能較預期慢一些。

補充:
當下大事件為中美貿易大戰,彭博資訊專欄作者 Fickling 指出,美國川普選擇開打貿易戰的日子選得真是好:中國正以歷史的縱深來打這場貿易戰。
費克林指出,川普在選擇升高貿易戰的時機上的確有一套。他在威脅數周之後,決定在9月18日再對2,000億美元中國產品開徵10%關稅,而「918」正是中國開始抵禦「日寇」侵略的重要日子,各機關、學校都有紀念活動,部分城市還會鳴響空襲警報,中共絕不會讓「918」深埋在歷史教科書中。
美國貿易談判官員一心想要以種種威脅,促使北京當局同意在經濟發展模式上做出重大改變。他們在決策的同時,應考慮到中南海的領導人絕不會僅執著於日常性的經濟鬥爭。
同時間,川普持續施壓要求聯準會主席鮑爾停止升息,並且希望各種手段促貶美元。
同時,川普還為了在墨西哥邊境築牆一事,不惜關閉政府來威脅民主黨就範。
















程式語言編年史

程式語言編年史原文 下面這張圖片描繪了整個程式語言的歷史。包括各種程式語言的發明人、程式語言的特點和適用領域、被什麼網站或公司使用等 (檢視 完整高清圖 )。 之所以會有那麼多不同的程式語言是因為設計程式語言的初衷不同、對語言學習曲線的追求不同、不同程式之間的執行成本差異...