github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/dsn/dsn.go (about) 1 package dsn 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 ) 8 9 // Flag is the datasource dsn structure. 10 type Flag struct { 11 Username, Password, Host string 12 Port int 13 Database string 14 } 15 16 // ParseFlag parses format like user:pass@host:port/db. 17 func ParseFlag(source string) (dc *Flag, err error) { 18 dc = &Flag{} 19 atPos := strings.LastIndex(source, "@") 20 if atPos < 0 { 21 err = fmt.Errorf("invalid source: %s, should be username:password@host:port", source) 22 return 23 } 24 25 userPart := source[:atPos] 26 if n := strings.IndexAny(userPart, "/:"); n > 0 { 27 if dc.Username = userPart[:n]; n+1 < len(userPart) { 28 dc.Password = userPart[n+1:] 29 } 30 } else { 31 dc.Username = userPart 32 } 33 34 if atPos+1 >= len(source) { 35 err = fmt.Errorf("invalid source: %s, should be username:password@host:port", source) 36 return 37 } 38 39 hostPart := source[atPos+1:] 40 41 if n := strings.LastIndex(hostPart, "/"); n > 0 { 42 dc.Database = hostPart[n+1:] 43 hostPart = hostPart[:n] 44 } 45 46 if n := strings.LastIndex(hostPart, ":"); n > 0 { 47 if dc.Host = hostPart[:n]; n+1 < len(hostPart) { 48 dc.Port, err = strconv.Atoi(hostPart[n+1:]) 49 if err != nil { 50 err = fmt.Errorf("port %s is not a number", hostPart[n+1:]) 51 return 52 } 53 } 54 } else { 55 dc.Host = hostPart 56 } 57 58 return 59 }