func writeFileResponse(filename string, bytes []byte, w http.ResponseWriter, r *http.Request) *model.AppError { w.Header().Set("Cache-Control", "max-age=2592000, public") w.Header().Set("Content-Length", strconv.Itoa(len(bytes))) w.Header().Del("Content-Type") // Content-Type will be set automatically by the http writer // attach extra headers to trigger a download on IE, Edge, and Safari ua := user_agent.New(r.UserAgent()) bname, _ := ua.Browser() parts := strings.Split(filename, "/") filePart := strings.Split(parts[len(parts)-1], "?")[0] w.Header().Set("Content-Disposition", "attachment;filename=\""+filePart+"\"") if bname == "Edge" || bname == "Internet Explorer" || bname == "Safari" { w.Header().Set("Content-Type", "application/octet-stream") } // prevent file links from being embedded in iframes w.Header().Set("X-Frame-Options", "DENY") w.Header().Set("Content-Security-Policy", "Frame-ancestors 'none'") w.Write(bytes) return nil }
// TextToCSV converts the specified text to an array of csv values func TextToCSV(text string) [][]string { lines := strings.Split(text, "\n") collection := [][]string{} // should we skip the header hasHeader := false if len(lines) > 1 { // first row should be the header hasHeader = true } // parse each line for idx, line := range lines { // ignore the first row if hasHeader { if idx == 0 { continue } } // get data from each line parts := strings.Split(line, ",") if len(parts) < minCSVRowLen { // ignore lines that don't have enough columns continue } collection = append(collection, parts) } return collection }
func SendEmail(to, subject, title, body string) bool { hp := strings.Split(host, ":") auth := smtp.PlainAuth("", username, password, hp[0]) var content_type string mailtype := "html" if mailtype == "html" { content_type = "Content-Type: text/" + mailtype + "; charset=UTF-8" } else { content_type = "Content-Type: text/plain" + "; charset=UTF-8" } // 登录之 body = strings.Replace(bodyTpl, "$body", body, 1) body = strings.Replace(body, "$title", title, 1) msg := []byte("To: " + to + "\r\nFrom: " + username + "<" + username + ">\r\nSubject: " + subject + "\r\n" + content_type + "\r\n\r\n" + body) send_to := strings.Split(to, ";") err := smtp.SendMail(host+":"+port, auth, username, send_to, msg) if err != nil { return false } return true }
/* returns a zero length list if no sites are found. */ func getSites(w http.ResponseWriter, r *http.Request) ([]siteQ, bool) { var sites = make([]siteQ, 0) for _, ns := range strings.Split(r.URL.Query().Get("sites"), ",") { nss := strings.Split(ns, ".") if len(nss) != 2 { web.BadRequest(w, r, "invalid sites query.") return sites, false } sites = append(sites, siteQ{networkID: nss[0], siteID: nss[1]}) } for _, s := range sites { err := db.QueryRow("select name FROM fits.site join fits.network using (networkpk) where siteid = $2 and networkid = $1", s.networkID, s.siteID).Scan(&s.name) if err == sql.ErrNoRows { web.NotFound(w, r, "invalid siteID and networkID combination: "+s.siteID+" "+s.networkID) return sites, false } if err != nil { web.ServiceUnavailable(w, r, err) return sites, false } } return sites, true }
func (r *resolver) handlePTRQuery(ptr string, query *dns.Msg) (*dns.Msg, error) { parts := []string{} if strings.HasSuffix(ptr, ptrIPv4domain) { parts = strings.Split(ptr, ptrIPv4domain) } else if strings.HasSuffix(ptr, ptrIPv6domain) { parts = strings.Split(ptr, ptrIPv6domain) } else { return nil, fmt.Errorf("invalid PTR query, %v", ptr) } host := r.backend.ResolveIP(parts[0]) if len(host) == 0 { return nil, nil } logrus.Debugf("Lookup for IP %s: name %s", parts[0], host) fqdn := dns.Fqdn(host) resp := new(dns.Msg) resp.SetReply(query) setCommonFlags(resp) rr := new(dns.PTR) rr.Hdr = dns.RR_Header{Name: ptr, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: respTTL} rr.Ptr = fqdn resp.Answer = append(resp.Answer, rr) return resp, nil }
/* * Function to format the reply of the PortFolio Stocks * @params stocks: String which holds values like `GOOGL:0:$656.99,APPL:5:$96.11` * @params stockdata: Stucture of the YAHOO API * @return: Formatted string like 'GOOGL:0:+$656.99','APPL:5:+$96.11' */ func format_reply_portfoliostocks(stocks string, stockdata *StockData) string { var value string stock := strings.Split(stocks, ",") for i := 0; i < len(stockdata.List.Resources); i++ { StockName := stockdata.List.Resources[i].Resource.Fields.Symbol for j := 0; j < len(stock); j++ { if !strings.EqualFold(StockName, strings.Split(stock[j], ":")[0]) { continue } CurrentMarketValue, _ := strconv.ParseFloat(stockdata.List.Resources[i].Resource.Fields.Price, 64) StockPrice, _ := strconv.ParseFloat(strings.Split(stock[j], ":")[2], 64) quantity := strings.Split(stock[j], ":")[1] value = value + ",'" + StockName + ":" + quantity if CurrentMarketValue > StockPrice { value = value + ":+$" } else if CurrentMarketValue < StockPrice { value = value + ":-$" } else { value = value + ":$" } value = value + strconv.FormatFloat(CurrentMarketValue, 'f', 2, 64) + "'" } } return strings.Trim(value, ",") }
func (d *Driver) GetIP() (string, error) { // DHCP is used to get the IP, so virtualbox hosts don't have IPs unless // they are running s, err := d.GetState() if err != nil { return "", err } if s != state.Running { return "", drivers.ErrHostIsNotRunning } output, err := drivers.RunSSHCommandFromDriver(d, "ip addr show dev eth1") if err != nil { return "", err } log.Debugf("SSH returned: %s\nEND SSH\n", output) // parse to find: inet 192.168.59.103/24 brd 192.168.59.255 scope global eth1 lines := strings.Split(output, "\n") for _, line := range lines { vals := strings.Split(strings.TrimSpace(line), " ") if len(vals) >= 2 && vals[0] == "inet" { return vals[1][:strings.Index(vals[1], "/")], nil } } return "", fmt.Errorf("No IP address found %s", output) }
// return true if data needs to be written here func QueueRemoteWrite(req *gomemcached.MCRequest) { key := req.Key nodeList := getVbucketNode(int(findShard(string(key)))) nodes := strings.Split(nodeList, ";") if len(nodes) < 1 { log.Fatal("Nodelist is empty. Cannot proceed") } if len(nodes) < 2 { //no replica return } var remoteNode string // figure out which is the remote host and queue to the write to that node for _, node := range nodes { found := false hostname := strings.Split(node, ":") for _, ip := range ipList { if ip == hostname[0] { found = true continue } } if found == false { remoteNode = node } } ri := &repItem{host: remoteNode, req: req, opcode: OP_REP} repChan <- ri return }
func decodeSecureCookie(value string) (user string, session string, err os.Error) { parts := strings.Split(value, "|", 3) if len(parts) != 3 { err = os.NewError("Malformed cookie value") return } val := parts[0] timestamp := parts[1] sig := parts[2] // Check signature if getCookieSig([]byte(val), timestamp) != sig { return "", "", os.NewError("Signature error, cookie is invalid") } // Check time stamp ts, _ := strconv.Atoi64(timestamp) if ts+maxAge < time.UTC().Seconds() { return "", "", os.NewError("Cookie is outdated") } buf := bytes.NewBufferString(val) encoder := base64.NewDecoder(base64.StdEncoding, buf) res, _ := ioutil.ReadAll(encoder) str := string(res) lst := strings.Split(str, "!", -1) if len(lst) != 2 { return "", "", os.NewError("Missing !") } return lst[0], lst[1], nil }
// TODO: This could use a unit test. func parseSwarm(hostURL string, h *host.Host) (string, error) { swarmOptions := h.HostOptions.SwarmOptions if !swarmOptions.Master { return "", fmt.Errorf("%q is not a swarm master. The --swarm flag is intended for use with swarm masters", h.Name) } u, err := url.Parse(swarmOptions.Host) if err != nil { return "", fmt.Errorf("There was an error parsing the url: %s", err) } parts := strings.Split(u.Host, ":") swarmPort := parts[1] // get IP of machine to replace in case swarm host is 0.0.0.0 mURL, err := url.Parse(hostURL) if err != nil { return "", fmt.Errorf("There was an error parsing the url: %s", err) } mParts := strings.Split(mURL.Host, ":") machineIP := mParts[0] hostURL = fmt.Sprintf("tcp://%s:%s", machineIP, swarmPort) return hostURL, nil }
func IsOwner(req *gomemcached.MCRequest) bool { key := req.Key nodeList := getVbucketNode(int(findShard(string(key)))) nodes := strings.Split(nodeList, ";") //log.Printf(" Nodes list %v key %s", nodes, string(key)) if strings.Contains(nodes[0], "localhost") || strings.Contains(nodes[0], "127.0.0.1") || nodes[0] == "" { return true } if len(nodes) < 1 { log.Fatal("Nodelist is empty. Cannot proceed") } for _, node := range nodes { hostname := strings.Split(node, ":") for _, ip := range ipList { if ip == hostname[0] { return true } } } return false }
func (s *initSystemSuite) TestNewServiceLogfile(c *gc.C) { s.conf.Logfile = "/var/log/juju/machine-0.log" service := s.newService(c) dirname := fmt.Sprintf("%s/init/%s", s.dataDir, s.name) script := ` #!/usr/bin/env bash # Set up logging. touch '/var/log/juju/machine-0.log' chown syslog:syslog '/var/log/juju/machine-0.log' chmod 0600 '/var/log/juju/machine-0.log' exec >> '/var/log/juju/machine-0.log' exec 2>&1 # Run the script. `[1:] + jujud + " machine-0" c.Check(service, jc.DeepEquals, &systemd.Service{ Service: common.Service{ Name: s.name, Conf: common.Conf{ Desc: s.conf.Desc, ExecStart: dirname + "/exec-start.sh", Logfile: "/var/log/juju/machine-0.log", }, }, UnitName: s.name + ".service", ConfName: s.name + ".service", Dirname: dirname, Script: []byte(script), }) // This gives us a more readable output if they aren't equal. c.Check(string(service.Script), gc.Equals, script) c.Check(strings.Split(string(service.Script), "\n"), jc.DeepEquals, strings.Split(script, "\n")) }
func getUsernameAndPassword(r *libhttp.Request) (string, string, error) { q := r.URL.Query() username, password := q.Get("u"), q.Get("p") if username != "" && password != "" { return username, password, nil } auth := r.Header.Get("Authorization") if auth == "" { return "", "", nil } fields := strings.Split(auth, " ") if len(fields) != 2 { return "", "", fmt.Errorf("Bad auth header") } bs, err := base64.StdEncoding.DecodeString(fields[1]) if err != nil { return "", "", fmt.Errorf("Bad encoding") } fields = strings.Split(string(bs), ":") if len(fields) != 2 { return "", "", fmt.Errorf("Bad auth value") } return fields[0], fields[1], nil }
func (me Version) compareTo(other Version) int { var ( meTab = strings.Split(string(me), ".") otherTab = strings.Split(string(other), ".") ) max := len(meTab) if len(otherTab) > max { max = len(otherTab) } for i := 0; i < max; i++ { var meInt, otherInt int if len(meTab) > i { meInt, _ = strconv.Atoi(meTab[i]) } if len(otherTab) > i { otherInt, _ = strconv.Atoi(otherTab[i]) } if meInt > otherInt { return 1 } if otherInt > meInt { return -1 } } return 0 }
// parseINI takes the contents of a credentials file and returns a map, whose keys // are the various profiles, and whose values are maps of the settings for the // profiles func parseINI(fileContents string) map[string]map[string]string { profiles := make(map[string]map[string]string) lines := strings.Split(fileContents, "\n") var currentSection map[string]string for _, line := range lines { // remove comments, which start with a semi-colon if split := strings.Split(line, ";"); len(split) > 1 { line = split[0] } // check if the line is the start of a profile. // // for example: // [default] // // otherwise, check for the proper setting // property=value if sectMatch := iniSectionRegexp.FindStringSubmatch(line); len(sectMatch) == 2 { currentSection = make(map[string]string) profiles[sectMatch[1]] = currentSection } else if setMatch := iniSettingRegexp.FindStringSubmatch(line); len(setMatch) == 3 && currentSection != nil { currentSection[setMatch[1]] = setMatch[2] } } return profiles }
func (r *PerfResult) ParseData() map[string]map[string]*ParsedPerfResult { if r.parsedData != nil { return r.parsedData } res := make(map[string]map[string]*ParsedPerfResult) for _, str := range r.Data { ss := strings.Split(str, "|") builder := ss[0] bench := ss[1] ok := ss[2] m := res[builder] if m == nil { m = make(map[string]*ParsedPerfResult) res[builder] = m } var p ParsedPerfResult p.OK = ok == "ok" p.Metrics = make(map[string]uint64) p.Artifacts = make(map[string]string) for _, entry := range ss[3:] { if strings.HasPrefix(entry, "file:") { ss1 := strings.Split(entry[len("file:"):], "=") p.Artifacts[ss1[0]] = ss1[1] } else { ss1 := strings.Split(entry, "=") val, _ := strconv.ParseUint(ss1[1], 10, 64) p.Metrics[ss1[0]] = val } } m[bench] = &p } r.parsedData = res return res }
func (blp *BinlogPlayer) dmlTableMatch(sqlSlice []string) bool { if blp.tables == nil { return true } if len(blp.tables) == 0 { return true } var firstKw string for _, sql := range sqlSlice { firstKw = strings.TrimSpace(strings.Split(sql, BLPL_SPACE)[0]) if firstKw != "insert" && firstKw != "update" && firstKw != "delete" { continue } streamCommentIndex := strings.Index(sql, BLPL_STREAM_COMMENT_START) if streamCommentIndex == -1 { //log.Warningf("sql doesn't have stream comment '%v'", sql) //If sql doesn't have stream comment, don't match return false } tableName := strings.TrimSpace(strings.Split(sql[(streamCommentIndex+len(BLPL_STREAM_COMMENT_START)):], BLPL_SPACE)[0]) for _, table := range blp.tables { if tableName == table { return true } } } return false }
func build(lines []string, line string, index int, z int, f string) { current_indent := check_indent(lines[index]) if current_indent == 0 { if len(line) > 0 { if s.Contains(line, ":") { add(`main["` + s.Split(line, ":")[0] + `"] = "` + s.Split(line, ":")[1] + `"`) } else { add(`main["` + line + `"] = ` + line) } } return } parent_indent := check_indent(lines[index-z]) parent := lines[index-z] parent = clear(parent) line = clear(line) if current_indent > parent_indent { if f == "n" { add(parent + `["` + line + `"] = ` + line) } if f == "k" { add(parent + `["` + s.Split(line, ":")[0] + `"] = "` + s.Split(line, ":")[1] + `"`) } } else { build(lines, line, index, z+1, f) } }
func (t *outputConfig) Set(value string) error { for _, s := range strings.Split(value, ",") { tags := strings.Split(s, "=") t.tags[tags[0]] = tags[1] } return nil }
// Unpacks a container name, returning the pod full name and container name we would have used to // construct the docker name. If we are unable to parse the name, an error is returned. func ParseDockerName(name string) (dockerName *KubeletContainerName, hash uint64, err error) { // For some reason docker appears to be appending '/' to names. // If it's there, strip it. name = strings.TrimPrefix(name, "/") parts := strings.Split(name, "_") if len(parts) == 0 || parts[0] != containerNamePrefix { err = fmt.Errorf("failed to parse Docker container name %q into parts", name) return nil, 0, err } if len(parts) < 6 { // We have at least 5 fields. We may have more in the future. // Anything with less fields than this is not something we can // manage. glog.Warningf("found a container with the %q prefix, but too few fields (%d): %q", containerNamePrefix, len(parts), name) err = fmt.Errorf("Docker container name %q has less parts than expected %v", name, parts) return nil, 0, err } nameParts := strings.Split(parts[1], ".") containerName := nameParts[0] if len(nameParts) > 1 { hash, err = strconv.ParseUint(nameParts[1], 16, 32) if err != nil { glog.Warningf("invalid container hash %q in container %q", nameParts[1], name) } } podFullName := parts[2] + "_" + parts[3] podUID := types.UID(parts[4]) return &KubeletContainerName{podFullName, podUID, containerName}, hash, nil }
func doRow0(top *Top, line string) { rexp := regexp.MustCompile(`top[\s\-0-9:]+up([:0-9A-z,\s]+?)([0-9] user.*)`) matches := rexp.FindStringSubmatch(line) if len(matches) != 3 { return } top.Uptime = strings.Trim(matches[1], " ,") ls := strings.Split(matches[2], ",") if len(ls) != 4 { return } // users ls[0] = strings.TrimSpace(ls[0]) top.Users, _ = strconv.Atoi(strings.Split(ls[0], " ")[0]) // load avgs // 5 if i := strings.Index(ls[1], "load average:"); i > -1 { ls[1] = strings.TrimSpace(ls[1][i+13:]) top.LoadAvg5, _ = strconv.ParseFloat(ls[1], 64) } // 10 top.LoadAvg10, _ = strconv.ParseFloat(strings.TrimSpace(ls[2]), 64) // 15 top.LoadAvg15, _ = strconv.ParseFloat(strings.TrimSpace(ls[3]), 64) }
func (k *kubernetes) tcFilterShow(bw string) error { if k.node.Name() == "k8master" { return nil } qdiscShow, err := k.node.runCommand("tc qdisc show") if err != nil { return err } qdiscoutput := strings.Split(qdiscShow, "ingress") vvport := strings.Split(qdiscoutput[1], "parent") vvPort := strings.Split(vvport[0], "dev ") cmd := fmt.Sprintf("tc -s filter show dev %s parent ffff:", vvPort[1]) str, err := k.node.runCommand(cmd) if err != nil { return err } output := strings.Split(str, "rate ") rate := strings.Split(output[1], "burst") regex := regexp.MustCompile("[0-9]+") outputStr := regex.FindAllString(rate[0], -1) outputInt, err := strconv.ParseInt(outputStr[0], 10, 64) bwInt, err := BwConvertInt64(bw) if err != nil { return err } if bwInt == outputInt { logrus.Infof("Applied bandwidth: %dkbits equals tc qdisc rate: %dkbits", bwInt, outputInt) } else { logrus.Errorf("Applied bandwidth: %dkbits does not match the tc rate: %d ", bwInt, outputInt) return errors.New("Applied bandwidth doe sot match the tc qdisc rate") } return nil }
func runAddr2Line(t *testing.T, exepath, addr string) (funcname, path, lineno string) { cmd := exec.Command(exepath, os.Args[0]) cmd.Stdin = strings.NewReader(addr) out, err := cmd.CombinedOutput() if err != nil { t.Fatalf("go tool addr2line %v: %v\n%s", os.Args[0], err, string(out)) } f := strings.Split(string(out), "\n") if len(f) < 3 && f[2] == "" { t.Fatal("addr2line output must have 2 lines") } funcname = f[0] pathAndLineNo := f[1] f = strings.Split(pathAndLineNo, ":") if runtime.GOOS == "windows" { switch len(f) { case 2: return funcname, f[0], f[1] case 3: return funcname, f[0] + ":" + f[1], f[2] default: t.Fatalf("no line number found in %q", pathAndLineNo) } } if len(f) != 2 { t.Fatalf("no line number found in %q", pathAndLineNo) } return funcname, f[0], f[1] }
func (t *StockMarketApp) HandleBuyStockRequest(args *Args, reply *Reply) error { stocks := strings.Split(args.StockData, ",") stockArray := make([]stock, len(stocks)) for i := 0; i < len(stocks); i++ { stockDetails := strings.Split(stocks[i], ":") stockName := stockDetails[0] sharePercentage, err := strconv.ParseFloat(strings.Replace(stockDetails[1], "%", "", -1), 64) if err != nil { log.Fatal(err) } stockObj := stock{symbol: stockName, percentage: float32(sharePercentage)} stockArray[i] = stockObj } getYahooData(&stockArray) var leftOverBalance float32 = 0.0 for i := 0; i < len(stockArray); i++ { stockBalanceShare := ((stockArray[i].percentage / 100.0) * args.Balance) stockArray[i].quantity = int(stockBalanceShare / stockArray[i].newNetAmount) if reply.Stocks != "" { reply.Stocks = reply.Stocks + "," + stockArray[i].symbol + ":" + strconv.Itoa(stockArray[i].quantity) + ":$" + fmt.Sprintf("%f", stockArray[i].newNetAmount) } else { reply.Stocks = stockArray[i].symbol + ":" + strconv.Itoa(stockArray[i].quantity) + ":$" + fmt.Sprintf("%f", stockArray[i].newNetAmount) } stockArray[i].leftOverBalance = stockBalanceShare - (float32(stockArray[i].quantity) * stockArray[i].newNetAmount) leftOverBalance = leftOverBalance + stockArray[i].leftOverBalance } reply.UnvestedAmount = leftOverBalance reply.TradeId = rand.Int() stockMarket = make(map[int][]stock) stockMarket[reply.TradeId] = stockArray return nil }
func parseURLPath(path string) (vid, fid, filename, ext string, isVolumeIdOnly bool) { switch strings.Count(path, "/") { case 3: parts := strings.Split(path, "/") vid, fid, filename = parts[1], parts[2], parts[3] ext = filepath.Ext(filename) case 2: parts := strings.Split(path, "/") vid, fid = parts[1], parts[2] dotIndex := strings.LastIndex(fid, ".") if dotIndex > 0 { ext = fid[dotIndex:] fid = fid[0:dotIndex] } default: sepIndex := strings.LastIndex(path, "/") commaIndex := strings.LastIndex(path[sepIndex:], ",") if commaIndex <= 0 { vid, isVolumeIdOnly = path[sepIndex+1:], true return } dotIndex := strings.LastIndex(path[sepIndex:], ".") vid = path[sepIndex+1 : commaIndex] fid = path[commaIndex+1:] ext = "" if dotIndex > 0 { fid = path[commaIndex+1 : dotIndex] ext = path[dotIndex:] } } return }
func (this *DbDumperManager) getPlanFromService() ([]string, error) { command := []string{"m"} output, err := this.cliCommand(command...) if err != nil { return nil, errors.New(strings.Join(output, "\n")) } if len(output) < 4 { return nil, errors.New(strings.Join(output, "\n")) } datasUnparsed := output[4:] var service string = "" for _, dataUnparsed := range datasUnparsed { dataUnparsedSplitted := strings.Split(dataUnparsed, " ") if dataUnparsedSplitted[0] != this.serviceName { continue } service = dataUnparsed } if service == "" { return nil, errors.New("Cannot found service: " + this.serviceName) } planString := strings.TrimPrefix(service, this.serviceName) planString = strings.TrimSpace(planString) plans := strings.Split(planString, ", ") lastPlanString := plans[len(plans)-1] lastPlan := strings.Split(lastPlanString, " ") plans[len(plans)-1] = lastPlan[0] return plans, nil }
func getToken(line, seperator string) string { tokens := strings.Split(line, seperator) if len(tokens) == 2 { return strings.Split(tokens[1], " ")[0] } return "" }
func verify() error { if flag.NArg() < 1 { return errors.New("No path was provided.") } if c && s { return sterrors.MutuallyExclusiveParameters("c", "s") } if Overwrite && Append { return sterrors.MutuallyExclusiveParameters("o", "a") } if c { Case = Camel } if s { Case = Snake } sterrors.Verbose = Verbose if IgnoredFieldsString != "" { IgnoredFields = strings.Split(IgnoredFieldsString, ",") } if IgnoredStructsString != "" { IgnoredStructs = strings.Split(IgnoredStructsString, ",") } return nil }
func (obj *Idcsv) load(t *tool.TFile) { headStr := t.NextLine(0) //the first line headArr := strings.Split(*headStr, ",") num := len(headArr) if num < 2 { fmt.Println("error format for dict") return } L: for { lineStr := t.Next() if lineStr == nil { break L } lineArr := strings.Split(*lineStr, ",") if len(lineArr) != num { fmt.Printf("error format string #%v#, bad num #%v#%v#\n", lineStr, len(lineArr), num) continue } for idx, str := range headArr { if str != "" || lineArr[idx] == "" { continue } obj.addItem(lineArr[idx-1], strings.Trim(lineArr[idx], " ")) } } }
// @WARNING: font to explode to must all have same height. func expandText(toExpand string) string { // First filter out newlines from original string toExpand = strings.Replace(toExpand, "\n", " ", -1) // create a list of large letters to format // Using a list instead of []string b/c utf8.RuneCountInString mismatches // the length with range when seeing fancy runes largeLetters := list.New() for _, r := range toExpand { char := string(r) largeLetters.PushBack(getLargeCharacter(char)) } // Now combine characters in the same row // Get num rows from a character (janky, @TODO:search for max row height) dummyLetter := strings.Split(getLargeCharacter("a"), "\n") rows := make([]string, len(dummyLetter)) for largeLetter := largeLetters.Front(); largeLetter != nil; largeLetter = largeLetter.Next() { splitStrings := strings.Split(largeLetter.Value.(string), "\n") for rowIndex, splitString := range splitStrings { rows[rowIndex] += "" + splitString } } // construct final string and add newlines at end of each row finalString := "" for _, row := range rows { finalString += row + " \n " } return finalString }