SEO是件賊有意思的事情 golang入坑系列


這兩天迷上了SEO。真心看不起百度的競價排名,但作為一個商業網站,賺錢是一件無可厚非的事情。只做活雷鋒,沒有大金主是做不長的。做完功課后,發現百度和google的SEO策略又不相同,幾乎是無法通用。百度目前占據着國內搜索市場70%的市場份額,雖然不齒百度的齷齪之舉,但也只能沉下心來好好琢磨琢磨百度的SEO策略。以前沒有接觸過SEO,不懂這里面的水。這兩天着了迷想好好研究研究SEO,才發現原來內容是否原創,網頁類型(靜態/動態),關鍵字覆蓋率,robots是否滿足要求,外鏈質量,網站結構都會影響到最終的排名。當然這里說的都是明面上的技術操作,沒提那些個灰色產業。既然稱之為灰色產業了,沒有老司機帶着,也很難明白是怎么運作的。問了一些買過SEO優化的朋友得知,有的SEO優化立竿見影,基本一周后就能沖到前10位,但不續費后,馬上下來(肯定有貓膩,但外行人還就是看不懂)。有的SEO會承諾保持多長時間,結果可想而知,這個排名會逐漸逐漸下降。以前感覺寫代碼是個技術活,最近一段時間越來越發現,寫代碼真心是個簡單的活,這些個說不清道不明,又能掙錢的才是技術活。這幾天有時間了,再看看SEO,看能不能把自己的博客也沖到前10名去。

但在沖前十之前,先堅持把這個系列寫完了。

<朝鮮三胖哥> 那一節,聊了一嘴,從普通類型轉換到interface{}是隱式轉換。這節就說一下interface{}這個類型吧,要不總感覺內容少一塊。反正也是入門級的書,聊嘛不是聊呀。我准備寫完了以后,出一個視頻系列,那會就改叫<golang脫口秀>。如果你有好的段子,好的想法或者要推廣嘛東西,歡迎發郵件給我(ztao8607@gmail.com),現在有一個影視公司已經下定了,其他人抓緊哦。

Golang中的interface{}有兩層含義,一層是單純的interface{},可以理解成Java的Object基類。因此所有的數據類型都可以轉化成interface{}。另外一層含義,就是接口類。這個接口類和Java的接口類又幾乎差不多,都是只聲明一些方法,而不具體實現。其實第一層里面的interface{}可以理解成特殊的接口類,這個接口類里面沒有聲明任何方法。所以兩層含義可以統一成一個事物。

如果直接把Java里面的接口含義拿過來,這就沒有意思了,也就不用寫Golang里面的接口類了。Golang的接口和Java的接口說到底本質相同,但模樣千秋。下面來看Golang中如何聲明一個接口:

type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

在聲明struct時候,是type name struct。這里聲明接口,是用type name interface,所以不用混淆了。在struct里面,都是各個成員屬性,而在interface里面,就都是各個成員函數。從這點來看,Golang和Java的interface聲明區別不大,大的區別在如何使用上面,Golang的使用要比Java靈活太多了。用事實來說話,看下面:

type Shape interface {
   area() float64
}

func getArea(shape Shape) float64 {
   return shape.area()
}

聲明了一個Shape的interface,里面有一個成員函數,是area,返回一個float64。而getArea只接受Shape接口類型。好,該上實現類了。

type Circle struct {
   x,y,radius float64
}
func(circle Circle) area() float64 {
   return math.Pi * circle.radius * circle.radius
}

現在Circle類就實現了剛才Shape的接口。不信,自己敲個代碼,驗證一下:

circle := Circle{x:0,y:0,radius:5}
fmt.Printf("Circle area: %f\n",getArea(circle))

嘿,一准兒能給你輸出結果。

如果只有一個實現類,那就體現不出接口的優勢了。再上一個實現類:

type Rectangle struct {
   width, height float64
}
func(rect Rectangle) area() float64 {
   return rect.width * rect.height
}
rectangle := Rectangle {width:10, height:5}
fmt.Printf("Rectangle area: %f\n",getArea(rectangle))

瞅瞅,又不一樣了吧。現在Rectangle和Circle都實現了Shape接口類。怎么實現的?如果你是從Java轉過來的,一定會默認去找extend關鍵字,瞅准了,上面可沒有extend關鍵字。

實現的秘密就在於Rectangle和Circle兩個類都有area() float64這個函數。所以在Golang當中,如何實現一個接口類?那就是把接口類中的函數都實現了,就成。

無論接口類中定義了幾個函數,都實現了。如果用不着,那就寫個函數聲明,里面加上空實現就可以。照這個邏輯,一個實現類理論上豈不是能實現無限個接口? 恩,是的,you are right!是這樣的!

如果一個項目中,代碼太多了,或者交接了好幾把手,等你分析代碼的時候,你都不知道這個類實現了多少個接口。正所謂有利有弊,Golang中接口的靈活性可以大大減少代碼量,減少耦合性。但也反過來降低了可讀性,舉個例子,如果程序出了bug,而這個bug恰恰出現在一個接口函數中,看代碼的時候,你都不知道是哪個實現類出的問題。別說使用go的debug工具,在線上很少會有通過debug打斷點進行調試的機會,一來線上環境這么容易進行debug,就說明太不安全了。理論上生產環境中的代碼都不應該包含debug信息。二來,有些問題只有在滿足一定條件,例如大流量,高並發,某些特殊請求下才能復現,貿然使用debug,已經破壞復現環境了,半天都找不到問題。所以建議在寫代碼的時候,一定要記得輸出日志,最好能在關鍵節點輸出盡可能的詳細日志。

Golang中的接口基本使用方法就是這些,如果你有Java基礎那么就沒有學習難度了。如果沒有,也沒關系,多寫幾個代碼也就差不多了。下面來看一下實際環境中經常使用到的接口:

type error interface {
   Error() string
}

沒錯,是Error。在此之前,我們都沒有考慮如果代碼出錯了怎么辦?所以這個時候就補上這個漏洞。Golang沒有try.. catch.. finally。所有的錯誤都是通過error來處理的,經典的代碼如下:

err := xxxxxx
if err != nil {
    ....
}

基本就是這樣,再高逼格的,就是把err在封裝成各種類型。但基本都是這樣一套處理方式。Golang也允許自己創建error信息,比如:

func Sqrt(value float64)(float64, error) {
   if(value < 0){
      return 0, errors.New("Math: negative number passed to Sqrt")
   }
   return math.Sqrt(value)
}

用戶可以通過errors.New()來創建自帶業務邏輯的錯誤信息。這方面就不多展開了,因為每個team都有自己的編碼規范,對error的處理方式也千奇百怪,沒法統一說明。但處理模式就上面那一套,所以最后來一個實際代碼結束Error:

package main

import "errors"
import "fmt"
import "math"

func Sqrt(value float64)(float64, error) {
   if(value < 0){
      return 0, errors.New("Math: negative number passed to Sqrt")
   }
   return math.Sqrt(value), nil
}
func main() {
   result, err:= Sqrt(-1)

   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println(result)
   }
   
   result, err = Sqrt(9)

   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println(result)
   }
}

我的博客即將搬運同步至騰訊雲+社區,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM