Commit cacf57bd4a044185604faf7d45dce09df11fc9cc
1 parent
d9855ed8cd
Exists in
master
merging with /utility package
Showing
7 changed files
with
611 additions
and
2 deletions
Show diff stats
default_values.go
File was created | 1 | package util | |
2 | |||
3 | // IntOrDefault ... | ||
4 | func IntOrDefault(v *int) int { | ||
5 | if v != nil { | ||
6 | return *v | ||
7 | } | ||
8 | return 0 | ||
9 | } | ||
10 | |||
11 | // Int32OrDefault ... | ||
12 | func Int32OrDefault(v *int32) int32 { | ||
13 | if v != nil { | ||
14 | return *v | ||
15 | } | ||
16 | return 0 | ||
17 | } | ||
18 | |||
19 | // Int64OrDefault ... | ||
20 | func Int64OrDefault(v *int64) int64 { | ||
21 | if v != nil { | ||
22 | return *v | ||
23 | } | ||
24 | return 0 | ||
25 | } | ||
26 | |||
27 | // Uint32OrDefault ... | ||
28 | func Uint32OrDefault(v *uint32) uint32 { | ||
29 | if v != nil { | ||
30 | return *v | ||
31 | } | ||
32 | return 0 | ||
33 | } | ||
34 | |||
35 | // Uint64OrDefault ... | ||
36 | func Uint64OrDefault(v *uint64) uint64 { | ||
37 | if v != nil { | ||
38 | return *v | ||
39 | } | ||
40 | return 0 | ||
41 | } | ||
42 | |||
43 | // StringOrDefault ... | ||
44 | func StringOrDefault(v *string) string { | ||
45 | if v != nil { | ||
46 | return *v | ||
47 | } | ||
48 | return "" | ||
49 | } | ||
50 | |||
51 | // Float32OrDefault ... | ||
52 | func Float32OrDefault(v *float32) float32 { | ||
53 | if v != nil { | ||
54 | return *v | ||
55 | } | ||
56 | return 0.0 | ||
57 | } | ||
58 | |||
59 | // Float64OrDefault ... | ||
60 | func Float64OrDefault(v *float64) float64 { | ||
61 | if v != nil { | ||
62 | return *v | ||
63 | } | ||
64 | return 0.0 | ||
65 | } | ||
66 |
diff.go
File was created | 1 | package util | |
2 | |||
3 | // Diff ... | ||
4 | func Diff(old, new []int64) (added, removed []int64) { | ||
5 | for i := range old { | ||
6 | isRemoved := true | ||
7 | for j := range new { | ||
8 | if old[i] == new[j] { | ||
9 | isRemoved = false | ||
10 | break | ||
11 | } | ||
12 | } | ||
13 | if isRemoved { | ||
14 | removed = append(removed, old[i]) | ||
15 | } | ||
16 | } | ||
17 | |||
18 | for i := range new { | ||
19 | isAdded := true | ||
20 | for j := range old { | ||
21 | if new[i] == old[j] { | ||
22 | isAdded = false | ||
23 | break | ||
24 | } | ||
25 | } | ||
26 | if isAdded { | ||
27 | added = append(added, new[i]) | ||
28 | } | ||
29 | } | ||
30 | |||
31 | return added, removed | ||
32 | } | ||
33 |
file_util.go
File was created | 1 | package util | |
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "io" | ||
6 | "io/ioutil" | ||
7 | "os" | ||
8 | "strings" | ||
9 | ) | ||
10 | |||
11 | func ReadFileContent(path string) ([]byte, error) { | ||
12 | f, err := os.Open(path) | ||
13 | if err != nil { | ||
14 | return nil, err | ||
15 | } | ||
16 | defer f.Close() | ||
17 | |||
18 | buf := &bytes.Buffer{} | ||
19 | if _, err = io.Copy(buf, f); err != nil { | ||
20 | return nil, err | ||
21 | } | ||
22 | |||
23 | return buf.Bytes(), nil | ||
24 | } | ||
25 | |||
26 | // ReadFileLines ... | ||
27 | func ReadFileLines(path string) ([]string, error) { | ||
28 | f, err := os.Open(path) | ||
29 | if err != nil { | ||
30 | return nil, err | ||
31 | } | ||
32 | defer f.Close() | ||
33 | |||
34 | var s strings.Builder | ||
35 | |||
36 | if _, err = io.Copy(&s, f); err != nil { | ||
37 | return nil, err | ||
38 | } | ||
39 | |||
40 | lines := strings.Split(s.String(), "\n") | ||
41 | for i := range lines { | ||
42 | lines[i] = strings.TrimRight(lines[i], "\r\n") | ||
43 | } | ||
44 | |||
45 | return lines, nil | ||
46 | } | ||
47 | |||
48 | // LinesToFile ... | ||
49 | func LinesToFile(path string, lines []string) error { | ||
50 | content := "" | ||
51 | for _, l := range lines { | ||
52 | content += l + "\n" | ||
53 | } | ||
54 | |||
55 | return ioutil.WriteFile(path, []byte(content), 0644) // drw-r--r-- | ||
56 | } | ||
57 | |||
58 | // InsertLine ... | ||
59 | func InsertLine(lines *[]string, pos int64, l string) { | ||
60 | tail := append([]string{l}, (*lines)[pos:]...) | ||
61 | |||
62 | *lines = append((*lines)[:pos], tail...) | ||
63 | } | ||
64 |
http.go
1 | package webutility | 1 | package webutility |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "encoding/json" | 4 | "encoding/json" |
5 | "fmt" | 5 | "fmt" |
6 | "net/http" | 6 | "net/http" |
7 | ) | 7 | ) |
8 | 8 | ||
9 | // StatusRecorder ... | 9 | // StatusRecorder ... |
10 | type StatusRecorder struct { | 10 | type StatusRecorder struct { |
11 | writer http.ResponseWriter | 11 | writer http.ResponseWriter |
12 | status int | 12 | status int |
13 | size int | 13 | size int |
14 | } | 14 | } |
15 | 15 | ||
16 | // NewStatusRecorder ... | 16 | // NewStatusRecorder ... |
17 | func NewStatusRecorder(w http.ResponseWriter) *StatusRecorder { | 17 | func NewStatusRecorder(w http.ResponseWriter) *StatusRecorder { |
18 | return &StatusRecorder{ | 18 | return &StatusRecorder{ |
19 | writer: w, | 19 | writer: w, |
20 | status: 0, | 20 | status: 0, |
21 | size: 0, | 21 | size: 0, |
22 | } | 22 | } |
23 | } | 23 | } |
24 | 24 | ||
25 | // WriteHeader is a wrapper http.ResponseWriter interface | 25 | // WriteHeader is a wrapper http.ResponseWriter interface |
26 | func (r *StatusRecorder) WriteHeader(code int) { | 26 | func (r *StatusRecorder) WriteHeader(code int) { |
27 | r.status = code | 27 | r.status = code |
28 | r.writer.WriteHeader(code) | 28 | r.writer.WriteHeader(code) |
29 | } | 29 | } |
30 | 30 | ||
31 | // Write is a wrapper for http.ResponseWriter interface | 31 | // Write is a wrapper for http.ResponseWriter interface |
32 | func (r *StatusRecorder) Write(in []byte) (int, error) { | 32 | func (r *StatusRecorder) Write(in []byte) (int, error) { |
33 | r.size = len(in) | 33 | r.size = len(in) |
34 | return r.writer.Write(in) | 34 | return r.writer.Write(in) |
35 | } | 35 | } |
36 | 36 | ||
37 | // Header is a wrapper for http.ResponseWriter interface | 37 | // Header is a wrapper for http.ResponseWriter interface |
38 | func (r *StatusRecorder) Header() http.Header { | 38 | func (r *StatusRecorder) Header() http.Header { |
39 | return r.writer.Header() | 39 | return r.writer.Header() |
40 | } | 40 | } |
41 | 41 | ||
42 | // Status ... | 42 | // Status ... |
43 | func (r *StatusRecorder) Status() int { | 43 | func (r *StatusRecorder) Status() int { |
44 | return r.status | 44 | return r.status |
45 | } | 45 | } |
46 | 46 | ||
47 | // Size ... | 47 | // Size ... |
48 | func (r *StatusRecorder) Size() int { | 48 | func (r *StatusRecorder) Size() int { |
49 | return r.size | 49 | return r.size |
50 | } | 50 | } |
51 | 51 | ||
52 | // NotFoundHandlerFunc writes HTTP error 404 to w. | 52 | // NotFoundHandlerFunc writes HTTP error 404 to w. |
53 | func NotFoundHandlerFunc(w http.ResponseWriter, req *http.Request) { | 53 | func NotFoundHandlerFunc(w http.ResponseWriter, req *http.Request) { |
54 | SetDefaultHeaders(w) | 54 | SetDefaultHeaders(w) |
55 | if req.Method == "OPTIONS" { | 55 | if req.Method == "OPTIONS" { |
56 | return | 56 | return |
57 | } | 57 | } |
58 | NotFound(w, req, fmt.Sprintf("Resource you requested was not found: %s", req.URL.String())) | 58 | NotFound(w, req, fmt.Sprintf("Resource you requested was not found: %s", req.URL.String())) |
59 | } | 59 | } |
60 | 60 | ||
61 | func SetContentType(w http.ResponseWriter, ctype string) { | ||
62 | w.Header().Set("Content-Type", ctype) | ||
63 | } | ||
64 | |||
65 | func SetResponseStatus(w http.ResponseWriter, status int) { | ||
66 | w.WriteHeader(status) | ||
67 | } | ||
68 | |||
69 | func WriteResponse(w http.ResponseWriter, content []byte) { | ||
70 | w.Write(content) | ||
71 | } | ||
72 | |||
61 | // SetDefaultHeaders set's default headers for an HTTP response. | 73 | // SetDefaultHeaders set's default headers for an HTTP response. |
62 | func SetDefaultHeaders(w http.ResponseWriter) { | 74 | func SetDefaultHeaders(w http.ResponseWriter) { |
63 | w.Header().Set("Access-Control-Allow-Origin", "*") | 75 | w.Header().Set("Access-Control-Allow-Origin", "*") |
64 | w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS") | 76 | w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS") |
65 | w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") | 77 | w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") |
66 | w.Header().Set("Content-Type", "application/json; charset=utf-8") | 78 | SetContentType(w, "application/json; charset=utf-8") |
67 | } | 79 | } |
68 | 80 | ||
69 | // GetLocale ... | 81 | // GetLocale ... |
70 | func GetLocale(req *http.Request, dflt string) string { | 82 | func GetLocale(req *http.Request, dflt string) string { |
71 | loc := req.FormValue("locale") | 83 | loc := req.FormValue("locale") |
72 | if loc == "" { | 84 | if loc == "" { |
73 | return dflt | 85 | return dflt |
74 | } | 86 | } |
75 | return loc | 87 | return loc |
76 | } | 88 | } |
77 | 89 | ||
78 | // Success ... | 90 | // Success ... |
79 | func Success(w http.ResponseWriter, payload interface{}, code int) { | 91 | func Success(w http.ResponseWriter, payload interface{}, code int) { |
80 | w.WriteHeader(code) | 92 | w.WriteHeader(code) |
81 | if payload != nil { | 93 | if payload != nil { |
82 | json.NewEncoder(w).Encode(payload) | 94 | json.NewEncoder(w).Encode(payload) |
83 | } | 95 | } |
84 | } | 96 | } |
85 | 97 | ||
86 | // OK ... | 98 | // OK ... |
87 | func OK(w http.ResponseWriter, payload interface{}) { | 99 | func OK(w http.ResponseWriter, payload interface{}) { |
88 | Success(w, payload, http.StatusOK) | 100 | Success(w, payload, http.StatusOK) |
89 | } | 101 | } |
90 | 102 | ||
91 | // Created ... | 103 | // Created ... |
92 | func Created(w http.ResponseWriter, payload interface{}) { | 104 | func Created(w http.ResponseWriter, payload interface{}) { |
93 | Success(w, payload, http.StatusCreated) | 105 | Success(w, payload, http.StatusCreated) |
94 | } | 106 | } |
95 | 107 | ||
96 | type weberror struct { | 108 | type weberror struct { |
97 | Request string `json:"request"` | 109 | Request string `json:"request"` |
98 | Error string `json:"error"` | 110 | Error string `json:"error"` |
99 | } | 111 | } |
100 | 112 | ||
101 | // Error ... | 113 | // Error ... |
102 | func Error(w http.ResponseWriter, r *http.Request, code int, err string) { | 114 | func Error(w http.ResponseWriter, r *http.Request, code int, err string) { |
103 | werr := weberror{Error: err, Request: r.Method + " " + r.RequestURI} | 115 | werr := weberror{Error: err, Request: r.Method + " " + r.RequestURI} |
104 | w.WriteHeader(code) | 116 | w.WriteHeader(code) |
105 | json.NewEncoder(w).Encode(werr) | 117 | json.NewEncoder(w).Encode(werr) |
106 | } | 118 | } |
107 | 119 | ||
108 | // BadRequest ... | 120 | // BadRequest ... |
109 | func BadRequest(w http.ResponseWriter, r *http.Request, err string) { | 121 | func BadRequest(w http.ResponseWriter, r *http.Request, err string) { |
110 | Error(w, r, http.StatusBadRequest, err) | 122 | Error(w, r, http.StatusBadRequest, err) |
111 | } | 123 | } |
112 | 124 | ||
113 | // Unauthorized ... | 125 | // Unauthorized ... |
114 | func Unauthorized(w http.ResponseWriter, r *http.Request, err string) { | 126 | func Unauthorized(w http.ResponseWriter, r *http.Request, err string) { |
115 | Error(w, r, http.StatusUnauthorized, err) | 127 | Error(w, r, http.StatusUnauthorized, err) |
116 | } | 128 | } |
117 | 129 | ||
118 | // Forbidden ... | 130 | // Forbidden ... |
119 | func Forbidden(w http.ResponseWriter, r *http.Request, err string) { | 131 | func Forbidden(w http.ResponseWriter, r *http.Request, err string) { |
120 | Error(w, r, http.StatusForbidden, err) | 132 | Error(w, r, http.StatusForbidden, err) |
121 | } | 133 | } |
122 | 134 | ||
123 | // NotFound ... | 135 | // NotFound ... |
124 | func NotFound(w http.ResponseWriter, r *http.Request, err string) { | 136 | func NotFound(w http.ResponseWriter, r *http.Request, err string) { |
125 | Error(w, r, http.StatusNotFound, err) | 137 | Error(w, r, http.StatusNotFound, err) |
126 | } | 138 | } |
127 | 139 | ||
128 | // Conflict ... | 140 | // Conflict ... |
129 | func Conflict(w http.ResponseWriter, r *http.Request, err string) { | 141 | func Conflict(w http.ResponseWriter, r *http.Request, err string) { |
130 | Error(w, r, http.StatusConflict, err) | 142 | Error(w, r, http.StatusConflict, err) |
131 | } | 143 | } |
132 | 144 | ||
133 | // InternalServerError ... | 145 | // InternalServerError ... |
134 | func InternalServerError(w http.ResponseWriter, r *http.Request, err string) { | 146 | func InternalServerError(w http.ResponseWriter, r *http.Request, err string) { |
135 | Error(w, r, http.StatusInternalServerError, err) | 147 | Error(w, r, http.StatusInternalServerError, err) |
136 | } | 148 | } |
137 |
int_util.go
File was created | 1 | package util | |
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "strconv" | ||
6 | ) | ||
7 | |||
8 | // ClampInt64 ... | ||
9 | func ClampInt64(v, min, max int64) int64 { | ||
10 | if v < min { | ||
11 | return min | ||
12 | } else if v > max { | ||
13 | return max | ||
14 | } | ||
15 | |||
16 | return v | ||
17 | } | ||
18 | |||
19 | // InRangeInt64 ... | ||
20 | func InRangeInt64(v, min, max int64) bool { | ||
21 | return (v >= min && v <= max) | ||
22 | } | ||
23 | |||
24 | // StringToInt64 ... | ||
25 | func StringToInt64(s string) int64 { | ||
26 | i, _ := strconv.ParseInt(s, 10, 64) | ||
27 | return i | ||
28 | } | ||
29 | |||
30 | // Int64ToString ... | ||
31 | func Int64ToString(i int64) string { | ||
32 | return fmt.Sprintf("%d", i) | ||
33 | } | ||
34 | |||
35 | // BoolToInt64 ... | ||
36 | func BoolToInt64(b bool) int64 { | ||
37 | if b { | ||
38 | return 1 | ||
39 | } | ||
40 | return 0 | ||
41 | } | ||
42 | |||
43 | // Int64ToBool ... | ||
44 | func Int64ToBool(i int64) bool { | ||
45 | return i != 0 | ||
46 | } | ||
47 |
nullables.go
File was created | 1 | package util | |
2 | |||
3 | import ( | ||
4 | "database/sql" | ||
5 | "database/sql/driver" | ||
6 | "encoding/json" | ||
7 | "fmt" | ||
8 | "time" | ||
9 | ) | ||
10 | |||
11 | // NullBool is a wrapper for sql.NullBool with added JSON (un)marshalling | ||
12 | type NullBool sql.NullBool | ||
13 | |||
14 | // Scan ... | ||
15 | func (nb *NullBool) Scan(value interface{}) error { | ||
16 | var b sql.NullBool | ||
17 | if err := b.Scan(value); err != nil { | ||
18 | nb.Bool, nb.Valid = false, false | ||
19 | return err | ||
20 | } | ||
21 | nb.Bool, nb.Valid = b.Bool, b.Valid | ||
22 | return nil | ||
23 | } | ||
24 | |||
25 | // Value ... | ||
26 | func (nb *NullBool) Value() (driver.Value, error) { | ||
27 | if !nb.Valid { | ||
28 | return nil, nil | ||
29 | } | ||
30 | return nb.Bool, nil | ||
31 | } | ||
32 | |||
33 | // MarshalJSON ... | ||
34 | func (nb NullBool) MarshalJSON() ([]byte, error) { | ||
35 | if nb.Valid { | ||
36 | return json.Marshal(nb.Bool) | ||
37 | } | ||
38 | |||
39 | return json.Marshal(nil) | ||
40 | } | ||
41 | |||
42 | // UnmarshalJSON ... | ||
43 | func (nb *NullBool) UnmarshalJSON(b []byte) error { | ||
44 | var temp *bool | ||
45 | if err := json.Unmarshal(b, &temp); err != nil { | ||
46 | return err | ||
47 | } | ||
48 | if temp != nil { | ||
49 | nb.Valid = true | ||
50 | nb.Bool = *temp | ||
51 | } else { | ||
52 | nb.Valid = false | ||
53 | } | ||
54 | return nil | ||
55 | } | ||
56 | |||
57 | // SQLCast ... | ||
58 | func (nb *NullBool) SQLCast() sql.NullBool { | ||
59 | return sql.NullBool(*nb) | ||
60 | } | ||
61 | |||
62 | // NullString is a wrapper for sql.NullString with added JSON (un)marshalling | ||
63 | type NullString sql.NullString | ||
64 | |||
65 | // Scan ... | ||
66 | func (ns *NullString) Scan(value interface{}) error { | ||
67 | var s sql.NullString | ||
68 | if err := s.Scan(value); err != nil { | ||
69 | ns.String, ns.Valid = "", false | ||
70 | return err | ||
71 | } | ||
72 | ns.String, ns.Valid = s.String, s.Valid | ||
73 | return nil | ||
74 | } | ||
75 | |||
76 | // Value ... | ||
77 | func (ns *NullString) Value() (driver.Value, error) { | ||
78 | if !ns.Valid { | ||
79 | return nil, nil | ||
80 | } | ||
81 | return ns.String, nil | ||
82 | } | ||
83 | |||
84 | // MarshalJSON ... | ||
85 | func (ns NullString) MarshalJSON() ([]byte, error) { | ||
86 | if ns.Valid { | ||
87 | return json.Marshal(ns.String) | ||
88 | } | ||
89 | return json.Marshal(nil) | ||
90 | } | ||
91 | |||
92 | // UnmarshalJSON ... | ||
93 | func (ns *NullString) UnmarshalJSON(b []byte) error { | ||
94 | var temp *string | ||
95 | if err := json.Unmarshal(b, &temp); err != nil { | ||
96 | return err | ||
97 | } | ||
98 | if temp != nil { | ||
99 | ns.Valid = true | ||
100 | ns.String = *temp | ||
101 | } else { | ||
102 | ns.Valid = false | ||
103 | } | ||
104 | return nil | ||
105 | } | ||
106 | |||
107 | // SQLCast ... | ||
108 | func (ns *NullString) SQLCast() sql.NullString { | ||
109 | return sql.NullString(*ns) | ||
110 | } | ||
111 | |||
112 | // NullInt64 is a wrapper for sql.NullInt64 with added JSON (un)marshalling | ||
113 | type NullInt64 sql.NullInt64 | ||
114 | |||
115 | // Scan ... | ||
116 | func (ni *NullInt64) Scan(value interface{}) error { | ||
117 | var i sql.NullInt64 | ||
118 | if err := i.Scan(value); err != nil { | ||
119 | ni.Int64, ni.Valid = 0, false | ||
120 | return err | ||
121 | } | ||
122 | ni.Int64, ni.Valid = i.Int64, i.Valid | ||
123 | return nil | ||
124 | } | ||
125 | |||
126 | // Value ... | ||
127 | func (ni *NullInt64) Value() (driver.Value, error) { | ||
128 | if !ni.Valid { | ||
129 | return nil, nil | ||
130 | } | ||
131 | return ni.Int64, nil | ||
132 | } | ||
133 | |||
134 | // MarshalJSON ... | ||
135 | func (ni NullInt64) MarshalJSON() ([]byte, error) { | ||
136 | if ni.Valid { | ||
137 | return json.Marshal(ni.Int64) | ||
138 | } | ||
139 | return json.Marshal(nil) | ||
140 | } | ||
141 | |||
142 | // UnmarshalJSON ... | ||
143 | func (ni *NullInt64) UnmarshalJSON(b []byte) error { | ||
144 | var temp *int64 | ||
145 | if err := json.Unmarshal(b, &temp); err != nil { | ||
146 | return err | ||
147 | } | ||
148 | if temp != nil { | ||
149 | ni.Valid = true | ||
150 | ni.Int64 = *temp | ||
151 | } else { | ||
152 | ni.Valid = false | ||
153 | } | ||
154 | return nil | ||
155 | } | ||
156 | |||
157 | // SQLCast ... | ||
158 | func (ni *NullInt64) SQLCast() sql.NullInt64 { | ||
159 | return sql.NullInt64(*ni) | ||
160 | } | ||
161 | |||
162 | // NullFloat64 is a wrapper for sql.NullFloat64 with added JSON (un)marshalling | ||
163 | type NullFloat64 sql.NullFloat64 | ||
164 | |||
165 | // Scan ... | ||
166 | func (nf *NullFloat64) Scan(value interface{}) error { | ||
167 | var f sql.NullFloat64 | ||
168 | if err := f.Scan(value); err != nil { | ||
169 | nf.Float64, nf.Valid = 0.0, false | ||
170 | return err | ||
171 | } | ||
172 | nf.Float64, nf.Valid = f.Float64, f.Valid | ||
173 | return nil | ||
174 | } | ||
175 | |||
176 | // Value ... | ||
177 | func (nf *NullFloat64) Value() (driver.Value, error) { | ||
178 | if !nf.Valid { | ||
179 | return nil, nil | ||
180 | } | ||
181 | return nf.Float64, nil | ||
182 | } | ||
183 | |||
184 | // MarshalJSON ... | ||
185 | func (nf NullFloat64) MarshalJSON() ([]byte, error) { | ||
186 | if nf.Valid { | ||
187 | return json.Marshal(nf.Float64) | ||
188 | } | ||
189 | return json.Marshal(nil) | ||
190 | } | ||
191 | |||
192 | // UnmarshalJSON ... | ||
193 | func (nf *NullFloat64) UnmarshalJSON(b []byte) error { | ||
194 | var temp *float64 | ||
195 | if err := json.Unmarshal(b, &temp); err != nil { | ||
196 | return err | ||
197 | } | ||
198 | if temp != nil { | ||
199 | nf.Valid = true | ||
200 | nf.Float64 = *temp | ||
201 | } else { | ||
202 | nf.Valid = false | ||
203 | } | ||
204 | return nil | ||
205 | } | ||
206 | |||
207 | // SQLCast ... | ||
208 | func (nf *NullFloat64) SQLCast() sql.NullFloat64 { | ||
209 | return sql.NullFloat64(*nf) | ||
210 | } | ||
211 | |||
212 | // NullTime ... | ||
213 | type NullTime struct { | ||
214 | Time time.Time | ||
215 | Valid bool // Valid is true if Time is not NULL | ||
216 | } | ||
217 | |||
218 | // Scan ... | ||
219 | func (nt *NullTime) Scan(value interface{}) (err error) { | ||
220 | if value == nil { | ||
221 | nt.Time, nt.Valid = time.Time{}, false | ||
222 | return | ||
223 | } | ||
224 | |||
225 | switch v := value.(type) { | ||
226 | case time.Time: | ||
227 | nt.Time, nt.Valid = v, true | ||
228 | return | ||
229 | case []byte: | ||
230 | nt.Time, err = parseDateTime(string(v), time.UTC) | ||
231 | nt.Valid = (err == nil) | ||
232 | return | ||
233 | case string: | ||
234 | nt.Time, err = parseDateTime(v, time.UTC) | ||
235 | nt.Valid = (err == nil) | ||
236 | return | ||
237 | } | ||
238 | |||
239 | nt.Valid = false | ||
240 | return fmt.Errorf("Can't convert %T to time.Time", value) | ||
241 | } | ||
242 | |||
243 | // Value implements the driver Valuer interface. | ||
244 | func (nt NullTime) Value() (driver.Value, error) { | ||
245 | if !nt.Valid { | ||
246 | return nil, nil | ||
247 | } | ||
248 | return nt.Time, nil | ||
249 | } | ||
250 | |||
251 | // MarshalJSON ... | ||
252 | func (nt NullTime) MarshalJSON() ([]byte, error) { | ||
253 | if nt.Valid { | ||
254 | format := nt.Time.Format("2006-01-02 15:04:05") | ||
255 | return json.Marshal(format) | ||
256 | } | ||
257 | return json.Marshal(nil) | ||
258 | } | ||
259 | |||
260 | // UnmarshalJSON ... | ||
261 | func (nt *NullTime) UnmarshalJSON(b []byte) error { | ||
262 | var temp *time.Time | ||
263 | var t1 time.Time | ||
264 | var err error | ||
265 | |||
266 | s1 := string(b) | ||
267 | s2 := s1[1 : len(s1)-1] | ||
268 | if s1 == "null" { | ||
269 | temp = nil | ||
270 | } else { | ||
271 | t1, err = time.Parse("2006-01-02 15:04:05", s2) | ||
272 | if err != nil { | ||
273 | return err | ||
274 | } | ||
275 | temp = &t1 | ||
276 | } | ||
277 | |||
278 | if temp != nil { | ||
279 | nt.Valid = true | ||
280 | nt.Time = *temp | ||
281 | } else { | ||
282 | nt.Valid = false | ||
283 | } | ||
284 | return nil | ||
285 | } | ||
286 | |||
287 | func parseDateTime(str string, loc *time.Location) (t time.Time, err error) { | ||
288 | base := "0000-00-00 00:00:00.0000000" | ||
289 | timeFormat := "2006-01-02 15:04:05.999999" | ||
290 | switch len(str) { | ||
291 | case 10, 19, 21, 22, 23, 24, 25, 26: // up to "YYYY-MM-DD HH:MM:SS.MMMMMM" | ||
292 | if str == base[:len(str)] { | ||
293 | return | ||
294 | } | ||
295 | t, err = time.Parse(timeFormat[:len(str)], str) | ||
296 | default: | ||
297 | err = fmt.Errorf("invalid time string: %s", str) | ||
298 | return | ||
299 | } | ||
300 | |||
301 | // Adjust location | ||
302 | if err == nil && loc != time.UTC { | ||
303 | y, mo, d := t.Date() | ||
304 | h, mi, s := t.Clock() | ||
305 | t, err = time.Date(y, mo, d, h, mi, s, t.Nanosecond(), loc), nil | ||
306 | } | ||
307 | |||
308 | return | ||
309 | } | ||
310 |
string_util.go
File was created | 1 | package util | |
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "strings" | ||
6 | ) | ||
7 | |||
8 | // IsWrappedWith ... | ||
9 | func IsWrappedWith(src, begin, end string) bool { | ||
10 | return strings.HasPrefix(src, begin) && strings.HasSuffix(src, end) | ||
11 | } | ||
12 | |||
13 | // ParseInt64Arr ... | ||
14 | func ParseInt64Arr(s, sep string) (arr []int64) { | ||
15 | s = strings.TrimSpace(s) | ||
16 | if s != "" { | ||
17 | parts := strings.Split(s, sep) | ||
18 | arr = make([]int64, len(parts)) | ||
19 | for i, p := range parts { | ||
20 | num := StringToInt64(p) | ||
21 | arr[i] = num | ||
22 | } | ||
23 | } | ||
24 | |||
25 | return arr | ||
26 | } | ||
27 | |||
28 | // Int64SliceToString ... | ||
29 | func Int64SliceToString(arr []int64) (s string) { | ||
30 | for i, num := range arr { | ||
31 | if i == 0 { | ||
32 | s += fmt.Sprintf("%d", num) | ||
33 | } else { | ||
34 | s += fmt.Sprintf(",%d", num) | ||
35 | } | ||
36 | } | ||
37 | |||
38 | return s | ||
39 | } | ||
40 | |||
41 | // CombineStrings ... | ||
42 | func CombineStrings(s1, s2, s3 string) string { | ||
43 | s1 = strings.TrimSpace(s1) | ||
44 | s2 = strings.TrimSpace(s2) | ||
45 | |||
46 | if s1 != "" && s2 != "" { | ||
47 | s1 += s3 + s2 | ||
48 | } else { | ||
49 | s1 += s2 | ||
50 | } | ||
51 | |||
52 | return s1 | ||
53 | } | ||
54 | |||
55 | // ReplaceAny replaces any of the characters from patern found in s with r and returns a new resulting string. | ||
56 | func ReplaceAny(s, patern, r string) (n string) { | ||
57 | n = s | ||
58 | for _, c := range patern { | ||
59 | n = strings.Replace(n, string(c), r, -1) | ||
60 | } | ||
61 | return n | ||
62 | } | ||
63 | |||
64 | func StringToBool(s string) bool { | ||
65 | s = strings.ToLower(s) | ||
66 | if s == "true" { | ||
67 | return true | ||
68 | } | ||
69 | return false | ||
70 | } | ||
71 | |||
72 | func BoolToString(b bool) string { | ||
73 | return fmt.Sprintf("%b", b) | ||
74 | } | ||
75 | |||
76 | func StringSliceContains(slice []string, s string) bool { | ||
77 | for i := range slice { | ||
78 | if slice[i] == s { | ||
79 | return true | ||
80 | } | ||
81 | } | ||
82 | return false | ||
83 | } | ||
84 |