├── .gitignore ├── LICENSE ├── README.md ├── cmd └── gotld │ └── main.go ├── data.go ├── go.mod ├── gotld.go └── gotld_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.sw* 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, jonsen yang 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | gotld 2 | ===== 3 | 4 | Get domain's tld by go 5 | 6 | 7 | ## Install gotld 8 | 9 | go get github.com/forease/gotld 10 | 11 | ## Import gotld 12 | 13 | import "github.com/forease/gotld" 14 | 15 | 16 | ## Use gotld 17 | 18 | For example. 19 | 20 | tld, domain, err := gotld.GetTld( *url ) 21 | if err != nil { 22 | fmt.Println( err ) 23 | return 24 | } 25 | fmt.Printf( "TLD: %s, Domain: %s\n", tld.Tld, domain ) 26 | 27 | ## About 28 | 29 | 北京实易时代科技有限公司 30 | Beijing ForEase Times Technology Co., Ltd. 31 | http://www.forease.net 32 | 33 | ## Contact me 34 | 35 | Jonsen Yang 36 | im16hot#gmail.com (replace # with @) 37 | -------------------------------------------------------------------------------- /cmd/gotld/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/forease/gotld" 9 | ) 10 | 11 | var url = flag.String("d", "", "check url") 12 | 13 | func main() { 14 | flag.Parse() 15 | 16 | if *url == "" { 17 | fmt.Println("Usage: -d www.forease.net") 18 | os.Exit(1) 19 | } 20 | 21 | tld, domain, err := gotld.GetTld(*url) 22 | if err != nil { 23 | fmt.Println(err) 24 | return 25 | } 26 | fmt.Printf("TLD: %s, Domain: %s\n", tld.Tld, domain) 27 | } 28 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/forease/gotld 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /gotld.go: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * 4 | */ 5 | package gotld 6 | 7 | import ( 8 | "bytes" 9 | "errors" 10 | "strings" 11 | "sync" 12 | ) 13 | 14 | // TldItem tld item 15 | type TldItem struct { 16 | Id int32 17 | Country, Tld, Category string 18 | Lables int 19 | } 20 | 21 | const ( 22 | GOTLD_VERSION = "gotld V1.3" 23 | ) 24 | 25 | var ( 26 | tldMap = make(map[string]TldItem) 27 | pool = sync.Pool{New: func() interface{} { return new(bytes.Buffer) }} 28 | ) 29 | 30 | // Initialization Top Level Domain Table 31 | func init() { 32 | initTld() 33 | } 34 | 35 | // GetTld 获取域名 36 | func GetTld(url string) (tld TldItem, domain string, err error) { 37 | tld, domain, _, err = subDomain(url, 0) 38 | 39 | return 40 | } 41 | 42 | // GetSubdomain 获取子域名 43 | func GetSubdomain(url string, level int) (subdomain, domain, tld string) { 44 | var t TldItem 45 | t, domain, subdomain, _ = subDomain(url, level) 46 | 47 | return subdomain, domain, t.Tld 48 | } 49 | 50 | func subDomain(url string, level int) (tld TldItem, domain, subDomain string, err error) { 51 | 52 | var ( 53 | buffer = pool.Get().(*bytes.Buffer) 54 | isTLD bool 55 | ) 56 | 57 | dm := strings.Split(url, ".") 58 | 59 | size := len(dm) 60 | if size > 1 { 61 | idx := 0 62 | 63 | for i := size - 1; i >= 0; i-- { 64 | // 组合域名 65 | for j := i; j < size; j++ { 66 | buffer.WriteString(dm[j]) 67 | if j != size-1 { 68 | buffer.WriteString(".") 69 | } 70 | } 71 | subDomain = buffer.String() 72 | 73 | // 重置buffer 74 | buffer.Reset() 75 | 76 | // 判断是否为TLD 77 | value, ok := tldMap[subDomain] 78 | if ok { 79 | tld = value 80 | isTLD = true 81 | continue 82 | } 83 | 84 | // 找出TLD后 85 | if isTLD { 86 | if domain == "" { 87 | domain = subDomain 88 | } 89 | if idx >= level { 90 | break 91 | } 92 | idx++ 93 | } 94 | } 95 | } else { 96 | tld, _ = tldMap[url] 97 | } 98 | 99 | pool.Put(buffer) 100 | 101 | if tld.Tld == "" { 102 | err = errors.New("Can't get tld from " + url) 103 | } else { 104 | tld.Lables = size 105 | } 106 | 107 | return 108 | } 109 | 110 | // GetVersion - 111 | func GetVersion() string { 112 | return GOTLD_VERSION 113 | } 114 | -------------------------------------------------------------------------------- /gotld_test.go: -------------------------------------------------------------------------------- 1 | package gotld 2 | 3 | import ( 4 | //"net" 5 | "fmt" 6 | "testing" 7 | ) 8 | 9 | var testUrls []string = []string{"www.google.com.hk", "www.forease.net", "com", 10 | "www.forease.com.cn", "www.ritto.shiga.jp", "ritto.shiga.jp", "jonsen.yang"} 11 | 12 | func TestGetTld(t *testing.T) { 13 | //url := "www.google.com.hk" 14 | for _, url := range testUrls { 15 | ss, dd, tld := GetSubdomain(url, 2) 16 | fmt.Println(ss, dd, tld) 17 | tldItem, domain, err := GetTld(url) 18 | if nil != err { 19 | t.Error("Failed get TLD:" + err.Error()) 20 | return 21 | } 22 | t.Logf("%s: %v, %s\n", url, tldItem.Tld, domain) 23 | } 24 | 25 | t.Fail() 26 | } 27 | 28 | func TestGetVersion(t *testing.T) { 29 | 30 | t.Logf("%s\n", GetVersion()) 31 | 32 | t.Fail() 33 | } 34 | 35 | func BenchmarkGetTld(b *testing.B) { 36 | b.ReportAllocs() 37 | b.ResetTimer() 38 | 39 | for i := 0; i < b.N; i++ { 40 | GetTld("www.aaa.bbb.ccc.ddd.forease.com.cn") 41 | } 42 | } 43 | 44 | func BenchmarkGetSubdomain(b *testing.B) { 45 | b.ReportAllocs() 46 | b.ResetTimer() 47 | 48 | for i := 0; i < b.N; i++ { 49 | GetSubdomain("www.aaa.bbb.ccc.ddd.forease.com.cn", 0) 50 | } 51 | } 52 | --------------------------------------------------------------------------------