chore: minor refactors based on static checks
- unchecked returns fixed (most) - remove unused constants - remove unsed structs - function parameters unused or incorrectly used - removed if else chains for error checks - use regex MustCompile instead of compile - spell checks - preallocate slice cap when size known - scope issues inside range
This commit is contained in:
parent
2c18d6356b
commit
712ad2d517
2
admin.go
2
admin.go
|
@ -38,7 +38,7 @@ func handleGetConfigScript(c echo.Context) error {
|
||||||
)
|
)
|
||||||
|
|
||||||
b.Write([]byte(`var CONFIG = `))
|
b.Write([]byte(`var CONFIG = `))
|
||||||
j.Encode(out)
|
_ = j.Encode(out)
|
||||||
return c.Blob(http.StatusOK, "application/javascript", b.Bytes())
|
return c.Blob(http.StatusOK, "application/javascript", b.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
campaigns.go
11
campaigns.go
|
@ -85,9 +85,11 @@ func handleGetCampaigns(c echo.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError,
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||||||
fmt.Sprintf("Error fetching campaigns: %s", pqErrMsg(err)))
|
fmt.Sprintf("Error fetching campaigns: %s", pqErrMsg(err)))
|
||||||
} else if single && len(out.Results) == 0 {
|
}
|
||||||
|
if single && len(out.Results) == 0 {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Campaign not found.")
|
return echo.NewHTTPError(http.StatusBadRequest, "Campaign not found.")
|
||||||
} else if len(out.Results) == 0 {
|
}
|
||||||
|
if len(out.Results) == 0 {
|
||||||
out.Results = make([]models.Campaign, 0)
|
out.Results = make([]models.Campaign, 0)
|
||||||
return c.JSON(http.StatusOK, out)
|
return c.JSON(http.StatusOK, out)
|
||||||
}
|
}
|
||||||
|
@ -492,7 +494,8 @@ func handleTestCampaign(c echo.Context) error {
|
||||||
|
|
||||||
// Send the test messages.
|
// Send the test messages.
|
||||||
for _, s := range subs {
|
for _, s := range subs {
|
||||||
if err := sendTestMessage(&s, &camp, app); err != nil {
|
sub := s
|
||||||
|
if err := sendTestMessage(&sub, &camp, app); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Error sending test: %v", err))
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Error sending test: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -500,7 +503,7 @@ func handleTestCampaign(c echo.Context) error {
|
||||||
return c.JSON(http.StatusOK, okResp{true})
|
return c.JSON(http.StatusOK, okResp{true})
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendTestMessage takes a campaign and a subsriber and sends out a sample campain message.
|
// sendTestMessage takes a campaign and a subsriber and sends out a sample campaign message.
|
||||||
func sendTestMessage(sub *models.Subscriber, camp *models.Campaign, app *App) error {
|
func sendTestMessage(sub *models.Subscriber, camp *models.Campaign, app *App) error {
|
||||||
if err := camp.CompileTemplate(app.Manager.TemplateFuncs(camp)); err != nil {
|
if err := camp.CompileTemplate(app.Manager.TemplateFuncs(camp)); err != nil {
|
||||||
return fmt.Errorf("Error compiling template: %v", err)
|
return fmt.Errorf("Error compiling template: %v", err)
|
||||||
|
|
|
@ -13,9 +13,6 @@ const (
|
||||||
// stdInputMaxLen is the maximum allowed length for a standard input field.
|
// stdInputMaxLen is the maximum allowed length for a standard input field.
|
||||||
stdInputMaxLen = 200
|
stdInputMaxLen = 200
|
||||||
|
|
||||||
// bodyMaxLen is the maximum allowed length for e-mail bodies.
|
|
||||||
bodyMaxLen = 1000000
|
|
||||||
|
|
||||||
// defaultPerPage is the default number of results returned in an GET call.
|
// defaultPerPage is the default number of results returned in an GET call.
|
||||||
defaultPerPage = 20
|
defaultPerPage = 20
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,5 @@ func newConfigFile() error {
|
||||||
return fmt.Errorf("error reading sample config (is binary stuffed?): %v", err)
|
return fmt.Errorf("error reading sample config (is binary stuffed?): %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ioutil.WriteFile("config.toml", b, 0644)
|
return ioutil.WriteFile("config.toml", b, 0644)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
10
lists.go
10
lists.go
|
@ -41,9 +41,11 @@ func handleGetLists(c echo.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError,
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||||||
fmt.Sprintf("Error fetching lists: %s", pqErrMsg(err)))
|
fmt.Sprintf("Error fetching lists: %s", pqErrMsg(err)))
|
||||||
} else if single && len(out.Results) == 0 {
|
}
|
||||||
|
if single && len(out.Results) == 0 {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "List not found.")
|
return echo.NewHTTPError(http.StatusBadRequest, "List not found.")
|
||||||
} else if len(out.Results) == 0 {
|
}
|
||||||
|
if len(out.Results) == 0 {
|
||||||
return c.JSON(http.StatusOK, okResp{[]struct{}{}})
|
return c.JSON(http.StatusOK, okResp{[]struct{}{}})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +143,9 @@ func handleDeleteLists(c echo.Context) error {
|
||||||
)
|
)
|
||||||
|
|
||||||
// Read the list IDs if they were sent in the body.
|
// Read the list IDs if they were sent in the body.
|
||||||
c.Bind(&ids)
|
if err := c.Bind(&ids); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if id < 1 && len(ids) == 0 {
|
if id < 1 && len(ids) == 0 {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Invalid ID.")
|
return echo.NewHTTPError(http.StatusBadRequest, "Invalid ID.")
|
||||||
|
|
34
main.go
34
main.go
|
@ -84,7 +84,9 @@ func init() {
|
||||||
f.Bool("new-config", false, "Generate sample config file")
|
f.Bool("new-config", false, "Generate sample config file")
|
||||||
|
|
||||||
// Process flags.
|
// Process flags.
|
||||||
f.Parse(os.Args[1:])
|
if err := f.Parse(os.Args[1:]); err != nil {
|
||||||
|
logger.Fatalf("error loading flags: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Display version.
|
// Display version.
|
||||||
if v, _ := f.GetBool("version"); v {
|
if v, _ := f.GetBool("version"); v {
|
||||||
|
@ -120,13 +122,15 @@ func init() {
|
||||||
}), nil); err != nil {
|
}), nil); err != nil {
|
||||||
logger.Fatalf("error loading config from env: %v", err)
|
logger.Fatalf("error loading config from env: %v", err)
|
||||||
}
|
}
|
||||||
ko.Load(posflag.Provider(f, ".", ko), nil)
|
if err := ko.Load(posflag.Provider(f, ".", ko), nil); err != nil {
|
||||||
|
logger.Fatalf("error loading config: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// initFileSystem initializes the stuffbin FileSystem to provide
|
// initFileSystem initializes the stuffbin FileSystem to provide
|
||||||
// access to bunded static assets to the app.
|
// access to bunded static assets to the app.
|
||||||
func initFileSystem(binPath string) (stuffbin.FileSystem, error) {
|
func initFileSystem(binPath string) (stuffbin.FileSystem, error) {
|
||||||
fs, err := stuffbin.UnStuff(os.Args[0])
|
fs, err := stuffbin.UnStuff(binPath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return fs, nil
|
return fs, nil
|
||||||
}
|
}
|
||||||
|
@ -158,17 +162,23 @@ func initFileSystem(binPath string) (stuffbin.FileSystem, error) {
|
||||||
// initMessengers initializes various messaging backends.
|
// initMessengers initializes various messaging backends.
|
||||||
func initMessengers(r *manager.Manager) messenger.Messenger {
|
func initMessengers(r *manager.Manager) messenger.Messenger {
|
||||||
// Load SMTP configurations for the default e-mail Messenger.
|
// Load SMTP configurations for the default e-mail Messenger.
|
||||||
var srv []messenger.Server
|
var (
|
||||||
for _, name := range ko.MapKeys("smtp") {
|
mapKeys = ko.MapKeys("smtp")
|
||||||
|
srv = make([]messenger.Server, 0, len(mapKeys))
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, name := range mapKeys {
|
||||||
if !ko.Bool(fmt.Sprintf("smtp.%s.enabled", name)) {
|
if !ko.Bool(fmt.Sprintf("smtp.%s.enabled", name)) {
|
||||||
logger.Printf("skipped SMTP: %s", name)
|
logger.Printf("skipped SMTP: %s", name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var s messenger.Server
|
var s messenger.Server
|
||||||
ko.Unmarshal("smtp."+name, &s)
|
if err := ko.Unmarshal("smtp."+name, &s); err != nil {
|
||||||
|
logger.Fatalf("error loading SMTP: %v", err)
|
||||||
|
}
|
||||||
s.Name = name
|
s.Name = name
|
||||||
s.SendTimeout = s.SendTimeout * time.Millisecond
|
s.SendTimeout *= time.Millisecond
|
||||||
srv = append(srv, s)
|
srv = append(srv, s)
|
||||||
|
|
||||||
logger.Printf("loaded SMTP: %s (%s@%s)", s.Name, s.Username, s.Host)
|
logger.Printf("loaded SMTP: %s (%s@%s)", s.Name, s.Username, s.Host)
|
||||||
|
@ -199,8 +209,12 @@ func main() {
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
var c constants
|
var c constants
|
||||||
ko.Unmarshal("app", &c)
|
if err := ko.Unmarshal("app", &c); err != nil {
|
||||||
ko.Unmarshal("privacy", &c.Privacy)
|
log.Fatalf("error loading app config: %v", err)
|
||||||
|
}
|
||||||
|
if err := ko.Unmarshal("privacy", &c.Privacy); err != nil {
|
||||||
|
log.Fatalf("error loading app config: %v", err)
|
||||||
|
}
|
||||||
c.RootURL = strings.TrimRight(c.RootURL, "/")
|
c.RootURL = strings.TrimRight(c.RootURL, "/")
|
||||||
c.UploadURI = filepath.Clean(c.UploadURI)
|
c.UploadURI = filepath.Clean(c.UploadURI)
|
||||||
c.UploadPath = filepath.Clean(c.UploadPath)
|
c.UploadPath = filepath.Clean(c.UploadPath)
|
||||||
|
@ -286,7 +300,7 @@ func main() {
|
||||||
app.Messenger = initMessengers(app.Manager)
|
app.Messenger = initMessengers(app.Manager)
|
||||||
|
|
||||||
// Initialize the workers that push out messages.
|
// Initialize the workers that push out messages.
|
||||||
go m.Run(time.Duration(time.Second * 5))
|
go m.Run(time.Second * 5)
|
||||||
m.SpawnWorkers()
|
m.SpawnWorkers()
|
||||||
|
|
||||||
// Initialize the HTTP server.
|
// Initialize the HTTP server.
|
||||||
|
|
|
@ -91,8 +91,8 @@ func New(cfg Config, src DataSource, notifCB models.AdminNotifCallback, l *log.L
|
||||||
notifCB: notifCB,
|
notifCB: notifCB,
|
||||||
logger: l,
|
logger: l,
|
||||||
messengers: make(map[string]messenger.Messenger),
|
messengers: make(map[string]messenger.Messenger),
|
||||||
camps: make(map[int]*models.Campaign, 0),
|
camps: make(map[int]*models.Campaign),
|
||||||
links: make(map[string]string, 0),
|
links: make(map[string]string),
|
||||||
subFetchQueue: make(chan *models.Campaign, cfg.Concurrency),
|
subFetchQueue: make(chan *models.Campaign, cfg.Concurrency),
|
||||||
msgQueue: make(chan *Message, cfg.Concurrency),
|
msgQueue: make(chan *Message, cfg.Concurrency),
|
||||||
msgErrorQueue: make(chan msgError, cfg.MaxSendErrors),
|
msgErrorQueue: make(chan msgError, cfg.MaxSendErrors),
|
||||||
|
@ -125,7 +125,7 @@ func (m *Manager) AddMessenger(msg messenger.Messenger) error {
|
||||||
|
|
||||||
// GetMessengerNames returns the list of registered messengers.
|
// GetMessengerNames returns the list of registered messengers.
|
||||||
func (m *Manager) GetMessengerNames() []string {
|
func (m *Manager) GetMessengerNames() []string {
|
||||||
var names []string
|
names := make([]string, 0, len(m.messengers))
|
||||||
for n := range m.messengers {
|
for n := range m.messengers {
|
||||||
names = append(names, n)
|
names = append(names, n)
|
||||||
}
|
}
|
||||||
|
|
5
media.go
5
media.go
|
@ -17,8 +17,7 @@ var imageMimes = []string{"image/jpg", "image/jpeg", "image/png", "image/svg", "
|
||||||
|
|
||||||
const (
|
const (
|
||||||
thumbPrefix = "thumb_"
|
thumbPrefix = "thumb_"
|
||||||
thumbWidth = 90
|
thumbnailSize = 90
|
||||||
thumbHeight = 90
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// handleUploadMedia handles media file uploads.
|
// handleUploadMedia handles media file uploads.
|
||||||
|
@ -52,7 +51,7 @@ func handleUploadMedia(c echo.Context) error {
|
||||||
fmt.Sprintf("Error opening image for resizing: %s", err))
|
fmt.Sprintf("Error opening image for resizing: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
t := imaging.Resize(src, thumbWidth, 0, imaging.Lanczos)
|
t := imaging.Resize(src, thumbnailSize, 0, imaging.Lanczos)
|
||||||
if err := imaging.Save(t, fmt.Sprintf("%s/%s%s", app.Constants.UploadPath, thumbPrefix, fName)); err != nil {
|
if err := imaging.Save(t, fmt.Sprintf("%s/%s%s", app.Constants.UploadPath, thumbPrefix, fName)); err != nil {
|
||||||
cleanUp = true
|
cleanUp = true
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError,
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||||||
|
|
|
@ -38,7 +38,8 @@ func NewEmailer(srv ...Server) (Messenger, error) {
|
||||||
servers: make(map[string]*Server),
|
servers: make(map[string]*Server),
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range srv {
|
for _, server := range srv {
|
||||||
|
s := server
|
||||||
var auth smtp.Auth
|
var auth smtp.Auth
|
||||||
if s.AuthProtocol == "cram" {
|
if s.AuthProtocol == "cram" {
|
||||||
auth = smtp.CRAMMD5Auth(s.Username, s.Password)
|
auth = smtp.CRAMMD5Auth(s.Username, s.Password)
|
||||||
|
|
|
@ -29,6 +29,6 @@ func MakeAttachmentHeader(filename, encoding string) textproto.MIMEHeader {
|
||||||
h := textproto.MIMEHeader{}
|
h := textproto.MIMEHeader{}
|
||||||
h.Set("Content-Disposition", "attachment; filename="+filename)
|
h.Set("Content-Disposition", "attachment; filename="+filename)
|
||||||
h.Set("Content-Type", "application/json; name=\""+filename+"\"")
|
h.Set("Content-Type", "application/json; name=\""+filename+"\"")
|
||||||
h.Set("Content-Transfer-Encoding", "base64")
|
h.Set("Content-Transfer-Encoding", encoding)
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,6 +232,6 @@ func drawTransparentImage(h, w int) []byte {
|
||||||
img = image.NewRGBA(image.Rect(0, 0, w, h))
|
img = image.NewRGBA(image.Rect(0, 0, w, h))
|
||||||
out = &bytes.Buffer{}
|
out = &bytes.Buffer{}
|
||||||
)
|
)
|
||||||
png.Encode(out, img)
|
_ = png.Encode(out, img)
|
||||||
return out.Bytes()
|
return out.Bytes()
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,7 +335,7 @@ func (s *Session) ExtractZIP(srcPath string, maxCSVs int) (string, []string, err
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var files []string
|
files := make([]string, 0, len(z.File))
|
||||||
for _, f := range z.File {
|
for _, f := range z.File {
|
||||||
fName := f.FileInfo().Name()
|
fName := f.FileInfo().Name()
|
||||||
|
|
||||||
|
@ -421,7 +421,7 @@ func (s *Session) LoadCSV(srcPath string, delim rune) error {
|
||||||
s.im.Unlock()
|
s.im.Unlock()
|
||||||
|
|
||||||
// Rewind, now that we've done a linecount on the same handler.
|
// Rewind, now that we've done a linecount on the same handler.
|
||||||
f.Seek(0, 0)
|
_, _ = f.Seek(0, 0)
|
||||||
rd := csv.NewReader(f)
|
rd := csv.NewReader(f)
|
||||||
rd.Comma = delim
|
rd.Comma = delim
|
||||||
|
|
||||||
|
|
|
@ -69,10 +69,13 @@ func handleGetSubscriber(c echo.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError,
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||||||
fmt.Sprintf("Error fetching subscriber: %s", pqErrMsg(err)))
|
fmt.Sprintf("Error fetching subscriber: %s", pqErrMsg(err)))
|
||||||
} else if len(out) == 0 {
|
}
|
||||||
|
if len(out) == 0 {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Subscriber not found.")
|
return echo.NewHTTPError(http.StatusBadRequest, "Subscriber not found.")
|
||||||
}
|
}
|
||||||
out.LoadLists(app.Queries.GetSubscriberLists)
|
if err := out.LoadLists(app.Queries.GetSubscriberLists); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Error loading lists for subscriber.")
|
||||||
|
}
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, okResp{out[0]})
|
return c.JSON(http.StatusOK, okResp{out[0]})
|
||||||
}
|
}
|
||||||
|
|
12
templates.go
12
templates.go
|
@ -28,10 +28,6 @@ const (
|
||||||
<p>Here is a link to <a href="https://listmonk.app" target="_blank">listmonk</a>.</p>`
|
<p>Here is a link to <a href="https://listmonk.app" target="_blank">listmonk</a>.</p>`
|
||||||
)
|
)
|
||||||
|
|
||||||
type dummyMessage struct {
|
|
||||||
UnsubscribeURL string
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
regexpTplTag = regexp.MustCompile(`{{(\s+)?template\s+?"content"(\s+)?\.(\s+)?}}`)
|
regexpTplTag = regexp.MustCompile(`{{(\s+)?template\s+?"content"(\s+)?\.(\s+)?}}`)
|
||||||
)
|
)
|
||||||
|
@ -56,12 +52,14 @@ func handleGetTemplates(c echo.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError,
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||||||
fmt.Sprintf("Error fetching templates: %s", pqErrMsg(err)))
|
fmt.Sprintf("Error fetching templates: %s", pqErrMsg(err)))
|
||||||
} else if single && len(out) == 0 {
|
}
|
||||||
|
if single && len(out) == 0 {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Template not found.")
|
return echo.NewHTTPError(http.StatusBadRequest, "Template not found.")
|
||||||
} else if len(out) == 0 {
|
|
||||||
return c.JSON(http.StatusOK, okResp{[]struct{}{}})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(out) == 0 {
|
||||||
|
return c.JSON(http.StatusOK, okResp{[]struct{}{}})
|
||||||
|
}
|
||||||
if single {
|
if single {
|
||||||
return c.JSON(http.StatusOK, okResp{out[0]})
|
return c.JSON(http.StatusOK, okResp{out[0]})
|
||||||
}
|
}
|
||||||
|
|
10
utils.go
10
utils.go
|
@ -27,11 +27,11 @@ var (
|
||||||
// filename_(number). The number is incremented in case
|
// filename_(number). The number is incremented in case
|
||||||
// new file uploads conflict with existing filenames
|
// new file uploads conflict with existing filenames
|
||||||
// on the filesystem.
|
// on the filesystem.
|
||||||
fnameRegexp, _ = regexp.Compile(`(.+?)_([0-9]+)$`)
|
fnameRegexp = regexp.MustCompile(`(.+?)_([0-9]+)$`)
|
||||||
|
|
||||||
// This replaces all special characters
|
// This replaces all special characters
|
||||||
tagRegexp, _ = regexp.Compile(`[^a-z0-9\-\s]`)
|
tagRegexp = regexp.MustCompile(`[^a-z0-9\-\s]`)
|
||||||
tagRegexpSpaces, _ = regexp.Compile(`[\s]+`)
|
tagRegexpSpaces = regexp.MustCompile(`[\s]+`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// ScanToStruct prepares a given set of Queries and assigns the resulting
|
// ScanToStruct prepares a given set of Queries and assigns the resulting
|
||||||
|
@ -248,7 +248,7 @@ func normalizeTags(tags []string) []string {
|
||||||
|
|
||||||
// makeMsgTpl takes a page title, heading, and message and returns
|
// makeMsgTpl takes a page title, heading, and message and returns
|
||||||
// a msgTpl that can be rendered as a HTML view. This is used for
|
// a msgTpl that can be rendered as a HTML view. This is used for
|
||||||
// rendering aribtrary HTML views with error and success messages.
|
// rendering arbitrary HTML views with error and success messages.
|
||||||
func makeMsgTpl(pageTitle, heading, msg string) msgTpl {
|
func makeMsgTpl(pageTitle, heading, msg string) msgTpl {
|
||||||
if heading == "" {
|
if heading == "" {
|
||||||
heading = pageTitle
|
heading = pageTitle
|
||||||
|
@ -265,7 +265,7 @@ func makeMsgTpl(pageTitle, heading, msg string) msgTpl {
|
||||||
// parses each number into an int64 and returns a slice of the
|
// parses each number into an int64 and returns a slice of the
|
||||||
// resultant values.
|
// resultant values.
|
||||||
func parseStringIDs(s []string) ([]int64, error) {
|
func parseStringIDs(s []string) ([]int64, error) {
|
||||||
var vals []int64
|
vals := make([]int64, 0, len(s))
|
||||||
|
|
||||||
for _, v := range s {
|
for _, v := range s {
|
||||||
i, err := strconv.ParseInt(v, 10, 64)
|
i, err := strconv.ParseInt(v, 10, 64)
|
||||||
|
|
Loading…
Reference in New Issue