ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

golang面试-代码编写题1-14

2022-07-19 18:34:05  阅读:155  来源: 互联网

标签:return 14 -- 代码 golang 面试 func 编写 string


目录

1.代码编写题--统计文本行数-bufio

func demo1() {
	file, err := os.Open("./Atest/1.txt")
	if err != nil {
		return
	}
	fd := bufio.NewScanner(file)
	count := 0
	for fd.Scan() {
		count++
	}
	fmt.Println(count)
}

2.代码编写题--多协程收集错误信息-channel

版本1

func demo1(num int) (string, error) {
	if num%2 == 0 {
		return "", fmt.Errorf("错误,num=%d", num)
	}
	return fmt.Sprintf("成功,num=%d", num), nil
}

func main() {
	wg := sync.WaitGroup{}
	errChan := make(chan error)
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(index int) {
			defer wg.Done()
			_, err := demo1(index)
			if err != nil {
				errChan <- err
			}
		}(i)
	}

	go func() {
		wg.Add(1)
		for {
			errStr, ok := <-errChan
			if ok {
				fmt.Println(errStr)
			} else {
				break
			}
		}
		wg.Done()
		close(errChan)
	}()
	
	time.Sleep(time.Second)
}

版本2

多协程收集错误信息升级,类型断言

func demo1(num int) (string, error) {
	if num%2 == 0 {
		return "", fmt.Errorf("错误,num=%d", num)
	}
	return fmt.Sprintf("成功,num=%d", num), nil
}

func main() {
	wg := sync.WaitGroup{}
	retChan := make(chan interface{})
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(index int) {
			defer wg.Done()
			data, err := demo1(index)
			if err != nil {
				retChan <- err
			} else {
				retChan <- data
			}
		}(i)
	}

	go func() {
		wg.Add(1)
		count := 0
		for {
			errStr, ok := <-retChan
			if ok {
				_, ok2 := errStr.(error)
				if ok2 {
					fmt.Println(errStr)
					count++
				}
			} else {
				break
			}

			if count >= 2 {
				break
			}
		}
		wg.Done()
		//close(retChan)
	}()

	time.Sleep(time.Second)
}

3.代码编写题--超时控制,内存泄露

版本1

版本1:会造成内训泄漏,阻塞在done <- struct{}{}
解决:使用缓存chan,因为有缓冲的chan是非阻塞的,直到写满缓冲长度才阻塞。可以适当的缓冲长度调大
done := make(chan struct{},1)
func demo() error {
	ctx, _ := context.WithTimeout(context.Background(), time.Second*1)
	done := make(chan struct{})
	go func() {
		//模拟业务
		time.Sleep(time.Millisecond * 1200)
		done <- struct{}{}
	}()

	select {
	case <-ctx.Done():
		return fmt.Errorf("超时")
	case <-done:
		return nil
	}
}

func main() {
	for i := 0; i < 100; i++ {
		go func() {
			demo()
		}()
	}

	for {
		time.Sleep(time.Second * 2)
		fmt.Println(runtime.NumGoroutine()) //打印当前运行的协程数量
	}

}

////////////////
101
101
101
101

版本2

func demo() error {
	ctx, _ := context.WithTimeout(context.Background(), time.Second*1)
	done := make(chan struct{},1)
	go func() {
		//模拟业务
		time.Sleep(time.Millisecond * 1200)
		done <- struct{}{}
	}()

	select {
	case <-ctx.Done():
		return fmt.Errorf("超时")
	case <-done:
		return nil
	}
}

func main() {
	for i := 0; i < 100; i++ {
		go func() {
			demo()
		}()
	}

	for {
		time.Sleep(time.Second * 2)
		fmt.Println(runtime.NumGoroutine()) //打印当前运行的协程数量
	}
}


///////////////
1
1
1

4.代码编写题--单例模式

方式1

type Person struct {
   Name string
}

var person *Person
var mu sync.Mutex

func NewPerson2(name string) *Person {
   if person != nil {
      //pass
   } else {
      mu.Lock()
      defer mu.Unlock()
      person = &Person{Name: name}
   }
   return person
}

func main() {
   p1 := NewPerson2("hallen1")
   p2 := NewPerson2("hallen2")
   fmt.Printf("%p\n", p1) // 0xc00008e1e0
   fmt.Printf("%p\n", p2) // 0xc00008e1e0
}

方式2:once.Do

var once sync.Once
var person *Person

type Person struct {
	Name string
}

func NewPerson2(name string) *Person {
	once.Do(func() {
		person = new(Person)
		person.Name = name
	})
	return person
}

func main() {
	p1 := NewPerson2("hallen1")
	p2 := NewPerson2("hallen2")
	fmt.Printf("%p\n", p1) // 0xc00008e1e0
	fmt.Printf("%p\n", p2) // 0xc00008e1e0
}

5.代码编写题--九九乘法表

func main() {
	for i := 1; i <= 9; i++ {
		for j := 1; j <= i; j++ {
			fmt.Printf("%d*%d=%d  ", j, i, i*j)
		}
		fmt.Println("  ")
	}
}
///////////
1*1=1    
1*2=2  2*2=4    
1*3=3  2*3=6  3*3=9    
1*4=4  2*4=8  3*4=12  4*4=16    
1*5=5  2*5=10  3*5=15  4*5=20  5*5=25    
1*6=6  2*6=12  3*6=18  4*6=24  5*6=30  6*6=36    
1*7=7  2*7=14  3*7=21  4*7=28  5*7=35  6*7=42  7*7=49    
1*8=8  2*8=16  3*8=24  4*8=32  5*8=40  6*8=48  7*8=56  8*8=64    
1*9=9  2*9=18  3*9=27  4*9=36  5*9=45  6*9=54  7*9=63  8*9=72  9*9=81

6.代码编写题--交替打印数字和字⺟

问题描述:使⽤两个 goroutine 交替打印序列,⼀个 goroutine 打印数字, 另外⼀个goroutine 打印字⺟, 最终效果如下:
12AB34CD56EF78GH910IJ1112KL1314MN1516OP1718QR1920ST2122UV2324WX2526YZ2728

解体思路:
问题很简单,使⽤ channel 来控制打印的进度。使⽤两个 channel ,来分别控制数字和字⺟的打印序列, 数字打印完成后通过 channel 通知字⺟打印, 字⺟打印完成后通知数字打印,然后周⽽复始的⼯作。
func main() {
	letter := make(chan bool)
	number := make(chan bool)
	wg := sync.WaitGroup{}

	go func() {
		i := 1
		for {
			select {
			case <-number:
				fmt.Print(i)
				i++
				fmt.Print(i)
				i++
				letter <- true
			}
		}
	}()
	wg.Add(1)

	go func() {
		i := 'A'
		for {
			select {
			case <-letter:
				if i >= 'Z' {
					wg.Done()
					return
				}
				fmt.Print(string(i))
				i++
				fmt.Print(string(i))
				i++
				number <- true
			}
		}
	}()

	number <- true
	wg.Wait()
}

7.代码编写题--依次打印猫狗鱼

问题描述:3个协程依次打印猫狗鱼
func main() {
	catChan := make(chan bool)
	dogChan := make(chan bool)
	fishChan := make(chan bool)
	wg := sync.WaitGroup{}

	go func() {
		wg.Add(1)
		for {
			select {
			case <-catChan:
				fmt.Print("猫")
				dogChan <- true
			}
		}
	}()

	go func() {
		wg.Add(1)
		for {
			select {
			case <-dogChan:
				fmt.Print("狗")
				fishChan <- true
			}
		}
	}()

	go func() {
		wg.Add(1)
		for {
			select {
			case <-fishChan:
				fmt.Print("鱼")
				catChan <- true
			}
		}
	}()

	catChan <- true
	wg.Wait()
}

8.代码编写题--判断字符串中字符是否全都不同

问题描述:
请实现⼀个算法,确定⼀个字符串的所有字符【是否全都不同】。这⾥我们要求【不允许使⽤额外的存储结构】。给定⼀个string,请返回⼀个bool值,true代表所有字符全都不同,false代表存在相同的字符。保证字符串中的字符为【ASCII字符】。字符串的⻓度⼩于等于【3000】。
解题思路:
这⾥有⼏个重点,第⼀个是ASCII字符, ASCII字符字符⼀共有256个,其中128个是常⽤字符,可以在键盘上输⼊。128之后的是键盘上⽆法找到的。
然后是全部不同,也就是字符串中的字符没有重复的,再次,不准使⽤额外的储存结构,且字符串⼩于等于3000。
如果允许其他额外储存结构,这个题⽬很好做。如果不允许的话,可以使⽤golang内置的⽅式实现。
//判断s字符串有几个不重复的v子串
strings.Count(s, string(v))

func isUniqueString(s string) bool {
	for _, v := range s {
		if v > 127 {
			return false
		}
		if strings.Count(s, string(v)) > 1 {
			return false
		}
	}
	return true
}

// strings.Index(s,string(v)) 判断字符串v在s字符串出现的位置,不存在返回-1
func isUniqueString2(s string) bool {
	for k,v := range s {
		if v > 127 {
			return false
		}
		if strings.Index(s,string(v)) != k {
			return false
		}
	}
	return true
}

9.代码编写题--翻转字符串

问题描述:
翻转给定字符串,abc-->cba

解题思路:
以字符串长度1/2为轴,前后反转赋值
func reverString(s string) string {
	str := []rune(s)
	l := len(str)
	for i := 0; i < l/2; i++ {
		str[i], str[l-1-i] = str[l-1-i], str[i]
	}
	return string(str)
}

10.代码编写题--判断两个给定的字符串排序后是否⼀致

问题描述:
给定两个字符串,请编写程序,确定其中⼀个字符串的字符重新排列后,能否变成另⼀个字符串。
这⾥规定【⼤⼩写为不同字符】,且考虑字符串重点空格。给定⼀个string s1和⼀个string s2,请返回⼀个bool,代表两串是否重新排列后可相同。

解决思路:
循环遍历s1,strings.Count数量在s2中是否相等
func isRegroup(s1, s2 string) bool {
	for _, v := range s1 {
		if strings.Count(s1, string(v)) != strings.Count(s2, string(v)) {
			return false
		}
	}
	return true
}

func main() {
	s1 := "abc"
	s2 := "cba"
	boo := isRegroup(s1, s2)
	fmt.Println(boo) //true
}

11.代码编写题--字符串替换

func replaceBlank(s, oldStr, newStr string) string {
	return strings.Replace(s, oldStr, newStr, -1)
}

func main() {
	s := "abcdeffff"
	res := replaceBlank(s, "f", "k")
	fmt.Println(res) //abcdekkkk
}

12.代码编写题--机器人坐标问题

问题描述:
有⼀个机器⼈,给⼀串指令,L左转 R右转,F前进⼀步,B后退⼀步,问最后机器⼈的坐标,最开始,机器⼈位于 0 0,⽅向为正Y。
可以输⼊重复指令n : ⽐如 R2(LF) 这个等于指令 RLFLF。
问最后机器⼈的坐标是多少?
//面朝方向: 1前 2右 3后 4左
// (0,0,1),x,y表示坐标,z表示面朝方向。支持的指令:L左转 R右转,F前进⼀步,B后退⼀步
func move(t [3]int, cmd string) [3]int {
	for _, v := range cmd {
		switch string(v) {
		case "L":
			//向左转
			if t[2] == 1 {
				t[2] = 4
			} else {
				t[2]--
			}
		case "R":
			//向右转
			if t[2] == 4 {
				t[2] = 1
			} else {
				t[2]++
			}
		case "F":
			//前进,看面朝方向
			if t[2] == 1 {
				//面朝前后改变y轴
				t[1]++
			} else if t[2] == 3 {
				t[1]--
			} else if t[2] == 2 {
				//面朝前后改变x轴
				t[0]++
			} else if t[2] == 4 {
				t[0]--
			}
		case "B":
			//后退,看面朝方向,面朝前后改变y轴
			if t[2] == 1 {
				//面朝前后改变y轴
				t[1]--
			} else if t[2] == 3 {
				t[1]++
			} else if t[2] == 2 {
				//面朝前后改变x轴
				t[0]--
			} else if t[2] == 4 {
				t[0]++
			}
		}
	}
	return t
}

func main() {
	t := [3]int{0, 0, 1} //初始值:机器人在原点,面朝前方
	re := move(t, "FFFFRFFF")
	fmt.Println(re)
}

13.代码编写题--实现两个channel打印五个随机数。生产消费模型

func main() {
	out := make(chan int, 1)
	wg := sync.WaitGroup{}
	wg.Add(2)

	go func() {
		defer wg.Done()
		defer close(out)
		for i := 0; i < 5; i++ {
			out <- rand.Intn(10)
		}
	}()

	go func() {
		defer wg.Done()
		for i := range out {
			fmt.Println(i)
		}
	}()
	wg.Wait()
}

14.代码编写题--补全代码,要求每秒钟调用一次proc并保证程序不退出

package main
func main() {
	go func() {
		// 1 在这⾥需要你写算法
		// 2 要求每秒钟调⽤⼀次proc函数
		// 3 要求程序不能退出
	}()
	select {}
}
func proc() {
	panic("ok")
}
解析:
题⽬主要考察了两个知识点:
1. 定时执⾏执⾏任务
2. 捕获 panic 错误
题⽬中要求每秒钟执⾏⼀次,⾸先想到的就是 time.Ticker 对象,该函数可每秒钟往chan 中放⼀个Time ,正好符合我们的要求。
在 golang 中捕获 panic ⼀般会⽤到 recover() 函数。

编写代码:

func main() {
	go func() {
		// 1 在这⾥需要你写算法
		// 2 要求每秒钟调⽤⼀次proc函数
		// 3 要求程序不能退出
		t := time.NewTicker(1 * time.Second)
		for {
			select {
			case <-t.C:
				go func() {
					defer func() {
						if err := recover(); err != nil {
							fmt.Println(err)
						}
					}()
					proc()
				}()
			}
		}
	}()
	select {}
}

func proc() {
	panic("ok")
}

标签:return,14,--,代码,golang,面试,func,编写,string
来源: https://www.cnblogs.com/guyouyin123/p/16495177.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有