Пользователь пока ничего не рассказал о себе

Наибольший вклад в теги

Все теги (5)

Лучшие ответы пользователя

Все ответы (10)
  • Почему код в одном случае работает, а в другом - нет и выдает ошибку?

    @Wirusnyy-chel
    Канал done у вас в обоих случаях не буфферизированый - это значит что для выполнения операции записи в канал должны быть готовы и писатель (ch<-val) и читатель (<-ch).

    В первом варианте у вас писатель готов совершить операцию, но у него нет читателя и этот поток исполнения ставится на паузу, до тех пор, пока не появится читатель, а читатель определён в этом же потоке поэтому его никогда не будет. Программа зависнет и может упасть с ошибкой.
    Это можно поправить сделав канал буфферизированным
    done := make(chan book, 1)


    Второй случай работает, т.к. писатель и читатель в разных потоках и могут дождаться друг друга.
    Ответ написан
    Комментировать
  • Как одновременно прочитать построчно два файла?

    @Wirusnyy-chel
    Из комментариев под вопросом:
    нужно из файла взять подстроку после : и проверить существует ли подстрока из 1 файла в подстроке файла 2(до :) и если она есть, то записать строку в виде: подстрока из 1 файла: подстрока из 2 файла

    размеры файлов до 1гб


    Быстрым будет вариант с мапой из ответа выше, но он будет потреблять достаточно много памяти и ищет только прямые вхождения подстроки 1 в подстроке 2.

    Предлагаю вариант с меньшим потреблением памяти
    file1, err := os.Open(config.First_file)
    if err != nil {
      log.Fatalln("error")
    }
    defer file1.Close()
    file1Scanner := bufio.NewScanner(file1)
    
    file2, err := os.Open(config.Second_file)
    if err != nil {
      log.Fatalln("error")
    }
    defer file2.Close()
    file2Scanner := bufio.NewScanner(file2)
    
    // находим все доступные подстроки из файла 2
    file2SubSrings := make([]string,0)
    for file2Scanner.Scan(){
      file2SubSrings = append(file2SubSrings, strings.Split(file2Scanner.Text(), ":")[0])
    }
    
    for file1Scanner.Scan() {
      file1SubString := strings.Split(file1Scanner.Text(), ":")[1]
      for _, val := range file2SubStrings{
        if strings.Contains(val, file1SubString) {
          log.Println(file1SubString, ":", val)
          break
        }
    }
    
    if err := file1Scanner.Err(); err != nil {
      log.Fatalln(err)
    }
    
    if err := file2Scanner.Err(); err != nil {
      log.Fatalln(err)
    }


    UPD Вариант с параллельностью
    func scanFiles(file1, file2 *bufio.Scanner) {
    	// находим все доступные подстроки из файла 2
    	file2SubStrings := make([]string, 0)
    	for file2.Scan() {
    		file2SubStrings = append(file2SubStrings, strings.Split(file2.Text(), ":")[0])
    	}
    
    	wg := new(sync.WaitGroup)
    	valChan := make(chan string)
    	for i := 0; i < 5; i++ {
    		wg.Add(1)
    		go findIntersections(valChan, file2SubStrings, wg)
    	}
    
    	for file1.Scan() {
    		valChan <- strings.Split(file1.Text(), ":")[1]
    	}
    
    	wg.Wait()
    }
    
    func findIntersections(values chan string, file2SubStrings []string, wg *sync.WaitGroup) {
    	for {
    		file1SubString, ok := <-values
    
    		if !ok {
    			wg.Done()
    			return
    		}
    
    		for _, val := range file2SubStrings {
    			if strings.Contains(val, file1SubString) {
    				log.Println(file1SubString, ":", val)
    				break
    			}
    		}
    	}
    }


    UPD2
    строка из файла 2 - 663624e4aae0164132f10f09fdd9fcd2:liberty_
    строка из файла 1 - scherbakovatd@example.com:663624e4aae0164132f10f09fdd9fcd2
    на выходе должно выйти scherbakovatd@example.com:liberty_

    func scanFiles(file1, file2 *bufio.Scanner) {
    	scanWg := new(sync.WaitGroup)
    	scanWg.Add(2)
    
    	file1SubStrings := make(map[string]string)
    	file2SubStrings := make(map[string]string)
    
    
    	go func() {
    		var substr []string
    		for file1.Scan() {
    			substr = strings.Split(file1.Text(), ":")
    			file1SubStrings[substr[1]] = substr[0]
    		}
    		scanWg.Done()
    	}()
    	
    	go func() {
    		var substr []string 
    		for file2.Scan() {
    			substr = strings.Split(file2.Text(), ":")
    			file2SubStrings[substr[0]] = substr[1]
    		}	
    		scanWg.Done()
    	}()
    	
    	scanWg.Wait()
    	
    	
    	wg := new(sync.WaitGroup)
    	valChan := make(chan struct{k,v string})
    	for i := 0; i < 5; i++ {
    		wg.Add(1)
    		go findIntersections(valChan, file2SubStrings, wg)
    	}
    
    	for k, v := range file1SubStrings {
    		valChan <- struct{ k, v string }{k: k, v: v}
    	}
    
    	wg.Wait()
    }
    
    func findIntersections(file1Values chan struct{ k,v string}, file2 map[string]string, wg *sync.WaitGroup) {
    	for {
    		file1, ok := <-file1Values
    
    		if !ok {
    			wg.Done()
    			return
    		}
    		
    		if file2Value, ok := file2[file1.k];ok {
    			log.Println(file1.k, ":", file2Value)
    		}
    	}
    }
    Ответ написан
  • Golang PGX как добавлять значения в jsonb?

    @Wirusnyy-chel
    Когда вы указываете
    '{$1}'
    постгрес воспринимает это как просто строку, а не как параметр для вставки.


    Пробовал явно указывать тип $1
    query := `
    UPDATE type
    SET characteristics = jsonb_insert(
    characteristics, '{$1}'::text, '{"type": "$2", "measure": "$3"}'::jsonb
    )
    WHERE id=$4`

    Так тоже ошибка : function jsonb_insert(jsonb, text, jsonb) does not exist

    У функции jsonb_insert сигнатура
    jsonb_insert(target jsonb, path text[], new_value jsonb [, insert_after boolean])
    Поэтому строка `'{$1}'::text'`, должна быть `'{$1}'::text[]'`. (Но и это не совсем поможет)

    Можно преобразовать это следующим образом:
    query := `
        UPDATE type
        SET characteristics = jsonb_insert(
            characteristics, array[$1::text], 
           jsonb_build_object('type', $2, 'measure', '$3')
        )
        WHERE id=$4`
    
      tag, err := conn.Exec(ctx, query,
        c.Name,      // string
        c.Type,      // string
        c.Measure,   // string
        c.ID,        // uint64
      )


    Или позволить pxg самому собрать jsonb:

    query := `
        UPDATE type
        SET characteristics = jsonb_insert(
            characteristics, array[$1::text], $2
        )
        WHERE id=$3`
    
      tag, err := conn.Exec(ctx, query,
        c.Name,      // string
       struct{ // лучше вынести как отдельный тип
         Type string `json:"type"`
         Measure string `json:"measure"`
        }{c.Type, c.Measure}
        c.ID,        // uint64
      )
    Ответ написан
    3 комментария
  • Как сжать файл?

    @Wirusnyy-chel
    Если нужно уменьшить размер бинарника который собирается гошкой https://habr.com/ru/company/plesk/blog/532402/

    Если хотите сжимать файлы для пересылки/хранения то перед использованием их нужно распаковать.
    Ответ написан
    Комментировать
  • Linter для Go для выявления переменных без явной инициализации?

    @Wirusnyy-chel
    Идея для проверки очень хорошая, но, судя по всему, такого литера ещё нет. Если найдёте или сами реализуете, пожалуйста отпишитесь.
    Есть близкий по смыслу https://github.com/GaijinEntertainment/go-exhaustruct

    Вариант с регулярной может помочь с реализацией необходимого вам поведения с помощью других линтеров.

    Идея как это реализовать.
    !! Warning похоже на небольшой костыль и сам это поведение не проверял!!
    Линтеры:
    1. Регулярка из ответа выше.
    2. https://github.com/gordonklaus/ineffassign
    3. Проверка на использование директивы nolint
    Алгоритм:
    1. Запрещаете неявную инициализации при помощи регулярки.
    2. Если переменная должна быть инициализирована дальше в коде, ineffassing выдаст ошибку, поэтому добавляем директиву nolint. Если этой инициализации не будет (ошибка которую хотим поймать) - упадёт проверка на использование nolint
    Ответ написан
    1 комментарий